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 
00044 #include "debug.h"
00045 #include "Error.h"
00046 #include "InternalErr.h"
00047 #include "Sequence.h"
00048 #include "DDS.h"
00049 #include "DataDDS.h"
00050 #include "util.h"
00051 #include "InternalErr.h"
00052 #include "escaping.h"
00053 
00054 using namespace std;
00055 
00056 static const unsigned char end_of_sequence = 0xA5; // binary pattern 1010 0101
00057 static const unsigned char start_of_instance = 0x5A; // binary pattern 0101 1010
00058 
00059 // Private member functions
00060 
00061 void
00062 Sequence::_duplicate(const Sequence &s)
00063 {
00064     d_row_number = s.d_row_number;
00065     d_starting_row_number = s.d_starting_row_number;
00066     d_ending_row_number = s.d_ending_row_number;
00067     d_row_stride = s.d_row_stride;
00068     d_leaf_sequence = s.d_leaf_sequence;
00069     d_unsent_data = s.d_unsent_data;
00070     d_wrote_soi = s.d_wrote_soi;
00071     d_top_most = s.d_top_most;
00072 
00073     Sequence &cs = const_cast<Sequence &>(s);
00074 
00075     // Copy the template BaseType objects.
00076     for (Vars_iter i = cs.var_begin(); i != cs.var_end(); i++) {
00077         add_var((*i)) ;
00078     }
00079 
00080     // Copy the BaseType objects used to hold values.
00081     for (vector<BaseTypeRow *>::iterator rows_iter = cs.d_values.begin();
00082          rows_iter != cs.d_values.end();
00083          rows_iter++) {
00084         // Get the current BaseType Row
00085         BaseTypeRow *src_bt_row_ptr = *rows_iter;
00086         // Create a new row.
00087         BaseTypeRow *dest_bt_row_ptr = new BaseTypeRow;
00088         // Copy the BaseType objects from a row to new BaseType objects.
00089         // Push new BaseType objects onto new row.
00090         for (BaseTypeRow::iterator bt_row_iter = src_bt_row_ptr->begin();
00091              bt_row_iter != src_bt_row_ptr->end();
00092              bt_row_iter++) {
00093             BaseType *src_bt_ptr = *bt_row_iter;
00094             BaseType *dest_bt_ptr = src_bt_ptr->ptr_duplicate();
00095             dest_bt_row_ptr->push_back(dest_bt_ptr);
00096         }
00097         // Push new row onto d_values.
00098         d_values.push_back(dest_bt_row_ptr);
00099     }
00100 }
00101 
00102 static void
00103 write_end_of_sequence(XDR *sink)
00104 {
00105     xdr_opaque(sink, (char *)&end_of_sequence, 1);
00106 }
00107 
00108 static void
00109 write_start_of_instance(XDR *sink)
00110 {
00111     xdr_opaque(sink, (char *)&start_of_instance, 1);
00112 }
00113 
00114 static unsigned char
00115 read_marker(XDR *source)
00116 {
00117     unsigned char marker;
00118     xdr_opaque(source, (char *)&marker, 1);
00119 
00120     return marker;
00121 }
00122 
00123 static bool
00124 is_start_of_instance(unsigned char marker)
00125 {
00126     return (marker == start_of_instance);
00127 }
00128 
00129 static bool
00130 is_end_of_sequence(unsigned char marker)
00131 {
00132     return (marker == end_of_sequence);
00133 }
00134 
00135 // Public member functions
00136 
00145 Sequence::Sequence(const string &n) : Constructor(n, dods_sequence_c),
00146         d_row_number(-1), d_starting_row_number(-1),
00147         d_row_stride(1), d_ending_row_number(-1),
00148         d_unsent_data(false), d_wrote_soi(false),
00149         d_leaf_sequence(false), d_top_most(false)
00150 {}
00151 
00153 Sequence::Sequence(const Sequence &rhs) : Constructor(rhs)
00154 {
00155     _duplicate(rhs);
00156 }
00157 
00158 BaseType *
00159 Sequence::ptr_duplicate()
00160 {
00161     return new Sequence(*this);
00162 }
00163 
00164 static inline void
00165 delete_bt(BaseType *bt_ptr)
00166 {
00167     DBG2(cerr << "In delete_bt: " << bt_ptr << endl);
00168     delete bt_ptr; bt_ptr = 0;
00169 }
00170 
00171 static inline void
00172 delete_rows(BaseTypeRow *bt_row_ptr)
00173 {
00174     DBG2(cerr << "In delete_rows: " << bt_row_ptr << endl);
00175 
00176     for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
00177 
00178     delete bt_row_ptr; bt_row_ptr = 0;
00179 }
00180 
00181 Sequence::~Sequence()
00182 {
00183     DBG2(cerr << "Entering Sequence::~Sequence" << endl);
00184     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00185         BaseType *btp = *i ;
00186         delete btp ; btp = 0;
00187     }
00188 
00189     for_each(d_values.begin(), d_values.end(), delete_rows);
00190     DBG2(cerr << "exiting Sequence::~Sequence" << endl);
00191 }
00192 
00193 Sequence &
00194 Sequence::operator=(const Sequence &rhs)
00195 {
00196     if (this == &rhs)
00197         return *this;
00198 
00199     dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
00200 
00201     _duplicate(rhs);
00202 
00203     return *this;
00204 }
00205 
00206 string
00207 Sequence::toString()
00208 {
00209     ostringstream oss;
00210 
00211     oss << BaseType::toString();
00212 
00213     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00214         oss << (*i)->toString();
00215     }
00216 
00217     oss << endl;
00218 
00219     return oss.str();
00220 }
00221 
00222 int
00223 Sequence::element_count(bool leaves)
00224 {
00225     if (!leaves)
00226         return _vars.size();
00227     else {
00228         int i = 0;
00229         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00230             i += (*iter)->element_count(true);
00231         }
00232         return i;
00233     }
00234 }
00235 
00236 bool
00237 Sequence::is_linear()
00238 {
00239     bool linear = true;
00240     bool seq_found = false;
00241     for (Vars_iter iter = _vars.begin(); linear && iter != _vars.end(); iter++) {
00242         if ((*iter)->type() == dods_sequence_c) {
00243             // A linear sequence cannot have more than one child seq. at any
00244             // one level. If we've already found a seq at this level, return
00245             // false.
00246             if (seq_found) {
00247                 linear = false;
00248                 break;
00249             }
00250             seq_found = true;
00251             linear = dynamic_cast<Sequence *>((*iter))->is_linear();
00252         }
00253         else if ((*iter)->type() == dods_structure_c) {
00254             linear = dynamic_cast<Structure*>((*iter))->is_linear();
00255         }
00256         else {
00257             // A linear sequence cannot have Arrays, Lists or Grids.
00258             linear = (*iter)->is_simple_type();
00259         }
00260     }
00261 
00262     return linear;
00263 }
00264 
00265 void
00266 Sequence::set_send_p(bool state)
00267 {
00268     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00269         (*i)->set_send_p(state);
00270     }
00271 
00272     BaseType::set_send_p(state);
00273 }
00274 
00275 void
00276 Sequence::set_read_p(bool state)
00277 {
00278     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00279         (*i)->set_read_p(state);
00280     }
00281 
00282     BaseType::set_read_p(state);
00283 }
00284 
00285 void
00286 Sequence::set_in_selection(bool state)
00287 {
00288     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00289         (*i)->set_in_selection(state);
00290     }
00291 
00292     BaseType::set_in_selection(state);
00293 }
00294 
00304 void
00305 Sequence::add_var(BaseType *bt, Part)
00306 {
00307     if (!bt)
00308         throw InternalErr(__FILE__, __LINE__,
00309                           "Cannot add variable: NULL pointer");
00310     // Jose Garcia
00311     // We append a copy of bt so the owner
00312     // of bt is free to deallocate as he wishes.
00313     DBG2(cerr << "In Sequence::add_var(), bt: " << bt << endl);
00314     DBG2(cerr << bt->toString() << endl);
00315 
00316     BaseType *bt_copy = bt->ptr_duplicate();
00317     bt_copy->set_parent(this);
00318     _vars.push_back(bt_copy);
00319 
00320     DBG2(cerr << "In Sequence::add_var(), bt_copy: " << bt_copy << endl);
00321     DBG2(cerr << bt_copy->toString() << endl);
00322 }
00323 
00324 // Deprecated
00325 BaseType *
00326 Sequence::var(const string &n, btp_stack &s)
00327 {
00328     string name = www2id(n);
00329 
00330     BaseType *btp = m_exact_match(name, &s);
00331     if (btp)
00332         return btp;
00333 
00334     return m_leaf_match(name, &s);
00335 }
00336 
00337 BaseType *
00338 Sequence::var(const string &name, bool exact_match, btp_stack *s)
00339 {
00340     string n = www2id(name);
00341 
00342     if (exact_match)
00343         return m_exact_match(n, s);
00344     else
00345         return m_leaf_match(n, s);
00346 }
00347 
00348 BaseType *
00349 Sequence::m_leaf_match(const string &name, btp_stack *s)
00350 {
00351     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00352         if ((*i)->name() == name) {
00353             if (s)
00354                 s->push(static_cast<BaseType *>(this));
00355             return *i;
00356         }
00357         if ((*i)->is_constructor_type()) {
00358             BaseType *btp = (*i)->var(name, false, s);
00359             if (btp) {
00360                 if (s)
00361                     s->push(static_cast<BaseType *>(this));
00362                 return btp;
00363             }
00364         }
00365     }
00366 
00367     return 0;
00368 }
00369 
00370 BaseType *
00371 Sequence::m_exact_match(const string &name, btp_stack *s)
00372 {
00373     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00374         if ((*i)->name() == name) {
00375             if (s)
00376                 s->push(static_cast<BaseType *>(this));
00377             return *i;
00378         }
00379     }
00380 
00381     string::size_type dot_pos = name.find("."); // zero-based index of `.'
00382     if (dot_pos != string::npos) {
00383         string aggregate = name.substr(0, dot_pos);
00384         string field = name.substr(dot_pos + 1);
00385 
00386         BaseType *agg_ptr = var(aggregate);
00387         if (agg_ptr) {
00388             if (s)
00389                 s->push(static_cast<BaseType *>(this));
00390             return agg_ptr->var(field, true, s); // recurse
00391         }
00392         else
00393             return 0;  // qualified names must be *fully* qualified
00394     }
00395 
00396     return 0;
00397 }
00398 
00403 BaseTypeRow *
00404 Sequence::row_value(size_t row)
00405 {
00406     if (row >= d_values.size())
00407         return 0;
00408     return d_values[row];
00409 }
00410 
00417 void
00418 Sequence::set_value(SequenceValues &values)
00419 {
00420     d_values = values;
00421 }
00422 
00425 SequenceValues
00426 Sequence::value()
00427 {
00428     return d_values;
00429 }
00430 
00436 BaseType *
00437 Sequence::var_value(size_t row, const string &name)
00438 {
00439     BaseTypeRow *bt_row_ptr = row_value(row);
00440     if (!bt_row_ptr)
00441         return 0;
00442 
00443     BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin();
00444     BaseTypeRow::iterator bt_row_end = bt_row_ptr->end();
00445     while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name)
00446         ++bt_row_iter;
00447 
00448     if (bt_row_iter == bt_row_end)
00449         return 0;
00450     else
00451         return *bt_row_iter;
00452 }
00453 
00459 BaseType *
00460 Sequence::var_value(size_t row, size_t i)
00461 {
00462     BaseTypeRow *bt_row_ptr = row_value(row);
00463     if (!bt_row_ptr)
00464         return 0;
00465 
00466     if (i >= bt_row_ptr->size())
00467         return 0;
00468 
00469     return (*bt_row_ptr)[i];
00470 }
00471 
00472 unsigned int
00473 Sequence::width()
00474 {
00475     unsigned int sz = 0;
00476 
00477     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00478         sz += (*i)->width();
00479     }
00480 
00481     return sz;
00482 }
00483 
00484 // This version returns -1. Each API-specific subclass should define a more
00485 // reasonable version. jhrg 5/24/96
00486 
00502 int
00503 Sequence::length()
00504 {
00505     return -1;
00506 }
00507 
00508 
00509 int
00510 Sequence::number_of_rows()
00511 {
00512     return d_values.size();
00513 }
00514 
00518 void
00519 Sequence::reset_row_number()
00520 {
00521     d_row_number = -1;
00522 }
00523 
00524 // Notes:
00525 // Assume that read() is implemented so that, when reading data for a nested
00526 // sequence, only the outer most level is *actually* read.
00527 // This is a consequence of our current (12/7/99) implementation of
00528 // the JGOFS server (which is the only server to actually use nested
00529 // sequences). 12/7/99 jhrg
00530 //
00531 // Stop assuming this. This logic is being moved into the JGOFS server
00532 // itself. 6/1/2001 jhrg
00533 
00534 // The read() function returns a boolean value, with TRUE
00535 // indicating that read() should be called again because there's
00536 // more data to read, and FALSE indicating there's no more data
00537 // to read. Note that this behavior is necessary to properly
00538 // handle variables that contain Sequences. Jose Garcia If an
00539 // error exists while reading, the implementers of the surrogate
00540 // library SHOULD throw an Error object which will propagate
00541 // beyond this point to to the original caller.
00542 // Jose Garcia
00543 
00569 bool
00570 Sequence::read_row(int row, const string &dataset, DDS &dds,
00571                    ConstraintEvaluator &eval, bool ce_eval)
00572 {
00573     DBG2(cerr << "Entering Sequence::read_row for " << name() << endl);
00574     if (row < d_row_number)
00575         throw InternalErr("Trying to back up inside a sequence!");
00576 
00577     DBG2(cerr << "read_row: row number " << row << ", current row " << d_row_number
00578          << endl);
00579     if (row == d_row_number)
00580         return true;
00581 
00582     dds.timeout_on();
00583 
00584     int eof = 0;  // Start out assuming EOF is false.
00585     while (!eof && d_row_number < row) {
00586         if (!read_p()) {
00587             eof = (read(dataset) == false);
00588         }
00589 
00590         // Advance the row number if ce_eval is false (we're not supposed to
00591         // evaluate the selection) or both ce_eval and the selection are
00592         // true.
00593         if (!eof && (!ce_eval || eval.eval_selection(dds, dataset)))
00594             d_row_number++;
00595 
00596         set_read_p(false); // ...so that the next instance will be read
00597     }
00598 
00599     // Once we finish the above loop, set read_p to true so that the caller
00600     // knows that data *has* been read. This is how the read() methods of the
00601     // elements of the sequence know to not call read() but instead look for
00602     // data values inside themselves.
00603     set_read_p(true);
00604 
00605     dds.timeout_off();
00606 
00607     // Return true if we have valid data, false if we've read to the EOF.
00608     return eof == 0;
00609 }
00610 
00611 // Private. This is used to process constraints on the rows of a sequence.
00612 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This
00613 // odd-looking logic first checks if d_ending_row_number is the sentinel
00614 // value of -1. If so, the sequence was not constrained by row number and
00615 // this method should never return true (which indicates that we're at the
00616 // end of a row-number constraint). If d_ending_row_number is not -1, then is
00617 // \e i at the end point? 6/1/2001 jhrg
00618 inline bool
00619 Sequence::is_end_of_rows(int i)
00620 {
00621     return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number));
00622 }
00623 
00684 bool
00685 Sequence::serialize(const string &dataset, ConstraintEvaluator &eval, DDS &dds,
00686                     XDR *sink, bool ce_eval)
00687 {
00688     DBG2(cerr << "Entering Sequence::serialize for " << name() << endl);
00689 
00690     // Special case leaf sequences!
00691     if (is_leaf_sequence())
00692         return serialize_leaf(dataset, dds, eval, sink, ce_eval);
00693     else
00694         return serialize_parent_part_one(dataset, dds, eval, sink);
00695 }
00696 
00697 // We know this is not a leaf Sequence. That means that this Sequence holds
00698 // another Sequence as one of its fields _and_ that child Sequence triggers
00699 // the actual transmission of values.
00700 
00701 bool
00702 Sequence::serialize_parent_part_one(const string &dataset, DDS &dds,
00703                                     ConstraintEvaluator &eval, XDR *sink)
00704 {
00705     DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl);
00706 
00707     int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
00708 
00709     // read_row returns true if valid data was read, false if the EOF was
00710     // found. 6/1/2001 jhrg
00711     // Since this is a parent sequence, read the row ignoring the CE (all of
00712     // the CE clauses will be evaluated by the leaf sequence).
00713     bool status = read_row(i, dataset, dds, eval, false);
00714     DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
00715 
00716     while (status && !is_end_of_rows(i)) {
00717         i += d_row_stride;
00718 
00719         // DBG(cerr << "Writing Start of Instance marker" << endl);
00720         // write_start_of_instance(sink);
00721 
00722         // In this loop serialize will signal an error with an exception.
00723         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00724             // Only call serialize for child Sequences; the leaf sequence
00725             // will trigger the transmission of values for its parents (this
00726             // sequence and maybe others) once it gets soem valid data to
00727             // send.
00728             // Note that if the leaf sequence has no variables in the current
00729             // projection, its serialize() method will never be called and that's
00730             // the method that triggers actually sending values. Thus the leaf
00731             // sequence must be the lowest level sequence with values whose send_p
00732             // property is true.
00733             if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c)
00734                 (*iter)->serialize(dataset, eval, dds, sink);
00735         }
00736 
00737         set_read_p(false); // ...so this will read the next instance
00738 
00739         status = read_row(i, dataset, dds, eval, false);
00740         DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
00741     }
00742     // Reset current row number for next nested sequence element.
00743     d_row_number = -1;
00744 
00745     // Always write the EOS marker? 12/23/04 jhrg
00746     // Yes. According to DAP2, a completely empty response is signalled by
00747     // a return value of only the EOS marker for the outermost sequence.
00748     if (d_top_most || d_wrote_soi) {
00749         DBG(cerr << "Writing End of Sequence marker" << endl);
00750         write_end_of_sequence(sink);
00751         d_wrote_soi = false;
00752     }
00753 
00754     return true;  // Signal errors with exceptions.
00755 }
00756 
00757 // If we are here then we know that this is 'parent sequence' and that the
00758 // leaf seq has found valid data to send. We also know that
00759 // serialize_parent_part_one has been called so data are in the instance's
00760 // fields. This is wheree we send data. Whereas ..._part_one() contains a
00761 // loop to iterate over all of rows in a parent sequence, this does not. This
00762 // method assumes that the serialize_leaf() will call it each time it needs
00763 // to be called.
00764 //
00765 // NB: This code only works if the child sequences appear after all other
00766 // variables.
00767 void
00768 Sequence::serialize_parent_part_two(const string &dataset, DDS &dds,
00769                                     ConstraintEvaluator &eval, XDR *sink)
00770 {
00771     DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl);
00772 
00773     BaseType *btp = get_parent();
00774     if (btp && btp->type() == dods_sequence_c)
00775         dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dataset, dds,
00776                 eval, sink);
00777 
00778     if (d_unsent_data) {
00779         DBG(cerr << "Writing Start of Instance marker" << endl);
00780         d_wrote_soi = true;
00781         write_start_of_instance(sink);
00782 
00783         // In this loop serialize will signal an error with an exception.
00784         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00785             // Send all the non-sequence variables
00786             DBG(cerr << "Sequence::serialize_parent_part_two(), serializing "
00787                 << (*iter)->name() << endl);
00788             if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
00789                 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
00790                 (*iter)->serialize(dataset, eval, dds, sink, false);
00791             }
00792         }
00793 
00794         d_unsent_data = false;              // read should set this.
00795     }
00796 }
00797 
00798 // This code is only run by a leaf sequence. Note that a one level sequence
00799 // is also a leaf sequence.
00800 bool
00801 Sequence::serialize_leaf(const string &dataset, DDS &dds,
00802                          ConstraintEvaluator &eval, XDR *sink, bool ce_eval)
00803 {
00804     DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl);
00805     int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
00806 
00807     // read_row returns true if valid data was read, false if the EOF was
00808     // found. 6/1/2001 jhrg
00809     bool status = read_row(i, dataset, dds, eval, ce_eval);
00810     DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
00811 
00812     // Once the first valid (satisfies the CE) row of the leaf sequence has
00813     // been read, we know we're going to send data. Send the current instance
00814     // of the parent/ancestor sequences now, if there are any. We only need
00815     // to do this once, hence it's not inside the while loop, but we only
00816     // send the parent seq data _if_ there's data in the leaf to send, that's
00817     // why we wait until after the first call to read_row() here in the leaf
00818     // sequence.
00819     //
00820     // NB: It's important to only call serialize_parent_part_two() for a
00821     // Sequence that really is the parent of a leaf sequence. The fancy cast
00822     // will throw and exception if btp is not a Sequence, but doesn't test
00823     // that it's a parent sequence as we've defined them here.
00824     if (status && !is_end_of_rows(i)) {
00825         BaseType *btp = get_parent();
00826         if (btp && btp->type() == dods_sequence_c)
00827             dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dataset,
00828                     dds, eval,
00829                     sink);
00830     }
00831 
00832     d_wrote_soi = false;
00833     while (status && !is_end_of_rows(i)) {
00834         i += d_row_stride;
00835 
00836         DBG(cerr << "Writing Start of Instance marker" << endl);
00837         d_wrote_soi = true;
00838         write_start_of_instance(sink);
00839 
00840         // In this loop serialize will signal an error with an exception.
00841         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00842             DBG(cerr << "Sequence::serialize_leaf(), serializing "
00843                 << (*iter)->name() << endl);
00844             if ((*iter)->send_p()) {
00845                 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
00846                 (*iter)->serialize(dataset, eval, dds, sink, false);
00847             }
00848         }
00849 
00850         set_read_p(false); // ...so this will read the next instance
00851 
00852         status = read_row(i, dataset, dds, eval, ce_eval);
00853         DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
00854     }
00855 
00856     // Only write the EOS marker if there's a matching Start Of Instnace
00857     // Marker in the stream.
00858     if (d_wrote_soi || d_top_most) {
00859         DBG(cerr << "Writing End of Sequence marker" << endl);
00860         write_end_of_sequence(sink);
00861     }
00862 
00863     return true;  // Signal errors with exceptions.
00864 }
00865 
00889 void
00890 Sequence::transfer_data(const string &dataset,
00891                         ConstraintEvaluator &eval,
00892                         DDS &dds)
00893 {
00894     DBG(cerr << "Entering Sequence::transfer_data for " << name() << endl);
00895 
00896     DBG(cerr << "Sequence::transfer_data, values: " << &d_values << endl);
00897 
00898     sequence_values_stack_t sequence_values_stack;
00899     sequence_values_stack.push_back(&d_values);
00900 
00901     transfer_data_private(dataset, eval, dds, sequence_values_stack);
00902 }
00903 
00904 void
00905 Sequence::transfer_data_private(const string &dataset,
00906                                 ConstraintEvaluator &eval,
00907                                 DDS &dds,
00908                                 sequence_values_stack_t &sequence_values_stack)
00909 {
00910     DBG(cerr << "Entering Sequence::transfer_data_private for " << name() << endl);
00911 
00912     if (is_leaf_sequence()) {
00913         transfer_data_for_leaf(dataset, dds, eval, sequence_values_stack);
00914     }
00915     else {
00916         transfer_data_parent_part_one(dataset, dds, eval, sequence_values_stack);
00917     }
00918 }
00919 
00920 void
00921 Sequence::transfer_data_for_leaf(const string &dataset, DDS &dds,
00922                                  ConstraintEvaluator &eval,
00923                                  sequence_values_stack_t &sequence_values_stack)
00924 {
00925     int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
00926 
00927     bool status = read_row(i, dataset, dds, eval, true);
00928 
00929     if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
00930         BaseType *btp = get_parent();
00931         if (btp && btp->type() == dods_sequence_c) {
00932             dynamic_cast<Sequence&>(*btp).transfer_data_parent_part_two(dataset, dds, eval, sequence_values_stack);
00933         }
00934     }
00935 
00936     SequenceValues *values = sequence_values_stack.back();
00937     DBG(cerr << "In td_for_leaf, using values = " << values << endl);
00938 
00939     while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
00940         i += get_row_stride();
00941 
00942         BaseTypeRow *row_data = new BaseTypeRow;
00943 
00944         // In this loop serialize will signal an error with an exception.
00945         for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
00946             if ((*iter)->send_p()) {
00947                 row_data->push_back((*iter)->ptr_duplicate());
00948             }
00949         }
00950 
00951         DBG(cerr << "Pushing values for " << name() << " to " << values << endl);
00952         // Save the row_data to the values().
00953         values->push_back(row_data);
00954         set_read_p(false);      // ...so this will read the next instance
00955         status = read_row(i, dataset, dds, eval, true);
00956     }
00957 
00958     sequence_values_stack.pop_back();
00959     DBG(cerr << "In td_for_leaf, Poping the top of the stack" << endl);;
00960 }
00961 
00962 
00963 void
00964 Sequence::transfer_data_parent_part_one(const string & dataset, DDS & dds,
00965                                         ConstraintEvaluator & eval,
00966                                         sequence_values_stack_t &
00967                                         sequence_values_stack)
00968 {
00969     DBG(cerr << "Entering transfer_data_parent_part_one for " << name() <<
00970         endl);
00971 
00972     int i =
00973         (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
00974 
00975     // read_row returns true if valid data was read, false if the EOF was
00976     // found. 6/1/2001 jhrg
00977     // Since this is a parent sequence, read the row ignoring the CE (all of
00978     // the CE clauses will be evaluated by the leaf sequence).
00979     bool status = read_row(i, dataset, dds, eval, false);
00980 
00981     while (status
00982            && (get_ending_row_number() == -1
00983                || i <= get_ending_row_number())) {
00984         i += get_row_stride();
00985         for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
00986             if ((*iter)->send_p()) {
00987                 switch ((*iter)->type()) {
00988                 case dods_sequence_c:
00989                     dynamic_cast <
00990                     Sequence & >(**iter).transfer_data_private(dataset,
00991                             eval,
00992                             dds,
00993                             sequence_values_stack);
00994                     break;
00995 
00996                 case dods_structure_c:
00997                     dynamic_cast <
00998                     Structure & >(**iter).transfer_data(dataset, eval, dds);
00999                     break;
01000 
01001                 default:
01002                     (*iter)->read(dataset);
01003                     break;
01004                 }
01005             }
01006         }
01007 
01008         set_read_p(false);      // ...so this will read the next instance
01009 
01010         status = read_row(i, dataset, dds, eval, false);
01011     }
01012 
01013     // Reset current row number for next nested sequence element.
01014     reset_row_number();
01015     sequence_values_stack.pop_back();
01016     DBG(cerr << "In td_fparent_part_one, Poping the top of the stack" <<
01017         endl);;
01018 }
01019 
01020 void
01021 Sequence::transfer_data_parent_part_two(const string &dataset, DDS &dds,
01022                                         ConstraintEvaluator &eval,
01023                                         sequence_values_stack_t &sequence_values_stack)
01024 {
01025     DBG(cerr << "Entering transfer_data_parent_part_two for " << name() << endl);
01026 
01027     BaseType *btp = get_parent();
01028     if (btp && btp->type() == dods_sequence_c) {
01029         dynamic_cast<Sequence&>(*btp).transfer_data_parent_part_two(dataset, dds, eval, sequence_values_stack);
01030     }
01031 
01032     SequenceValues *values = sequence_values_stack.back();
01033     DBG(cerr << "In td_parent_part_two, using values = " << values << endl);
01034 
01035     if (get_unsent_data()) {
01036         BaseTypeRow *row_data = new BaseTypeRow;
01037 
01038         // In this loop transfer_data will signal an error with an exception.
01039         for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
01040 
01041             if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
01042                 row_data->push_back((*iter)->ptr_duplicate());
01043             }
01044             else if ((*iter)->send_p()) { //Sequence, and it must be last the variable
01045                 Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate());
01046                 row_data->push_back(tmp);
01047                 DBG(cerr << "In td_parent_part_two, pushing values = "
01048                     << &(dynamic_cast<Sequence&>(*tmp).d_values) << endl);
01049                 sequence_values_stack.push_back(&(dynamic_cast<Sequence&>(*tmp).d_values));
01050             }
01051         }
01052 
01053         DBG(cerr << "Pushing values for " << name() << " to " << values << endl);
01054         values->push_back(row_data);
01055         set_unsent_data(false);
01056     }
01057 }
01058 
01059 
01077 bool
01078 Sequence::deserialize(XDR *source, DDS *dds, bool reuse)
01079 {
01080     DataDDS *dd = dynamic_cast<DataDDS *>(dds);
01081     if (!dd)
01082         throw InternalErr("Expected argument 'dds' to be a DataDDS!");
01083 
01084     DBG2(cerr << "Reading from server/protocol version: "
01085          << dd->get_protocol_major() << "." << dd->get_protocol_minor()
01086          << endl);
01087 
01088     // Check for old servers.
01089     if (dd->get_protocol_major() < 2) {
01090         throw Error(string("The protocl version (") + dd->get_protocol() 
01091                     + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator.");
01092     }
01093 
01094     while (true) {
01095         // Grab the sequence stream's marker.
01096         unsigned char marker = read_marker(source);
01097         if (is_end_of_sequence(marker))
01098             break;  // EXIT the while loop here!!!
01099         else if (is_start_of_instance(marker)) {
01100             d_row_number++;
01101             DBG2(cerr << "Reading row " << d_row_number << " of "
01102                  << name() << endl);
01103             BaseTypeRow *bt_row_ptr = new BaseTypeRow;
01104             // Read the instance's values, building up the row
01105             for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
01106                 BaseType *bt_ptr = (*iter)->ptr_duplicate();
01107                 bt_ptr->deserialize(source, dds, reuse);
01108                 DBG2(cerr << "Deserialized " << bt_ptr->name() << " ("
01109                      << bt_ptr << ") = ");
01110                 DBG2(bt_ptr->print_val(stderr, ""));
01111                 bt_row_ptr->push_back(bt_ptr);
01112             }
01113             // Append this row to those accumulated.
01114             d_values.push_back(bt_row_ptr);
01115         }
01116         else
01117             throw Error("I could not read the expected Sequence data stream marker!");
01118     };
01119 
01120     return false;
01121 }
01122 
01123 // Return the current row number.
01124 
01136 int
01137 Sequence::get_starting_row_number()
01138 {
01139     return d_starting_row_number;
01140 }
01141 
01152 int
01153 Sequence::get_row_stride()
01154 {
01155     return d_row_stride;
01156 }
01157 
01169 int
01170 Sequence::get_ending_row_number()
01171 {
01172     return d_ending_row_number;
01173 }
01174 
01183 void
01184 Sequence::set_row_number_constraint(int start, int stop, int stride)
01185 {
01186     if (stop < start)
01187         throw Error(malformed_expr, "Starting row number must precede the ending row number.");
01188 
01189     d_starting_row_number = start;
01190     d_row_stride = stride;
01191     d_ending_row_number = stop;
01192 }
01193 
01196 unsigned int
01197 Sequence::val2buf(void *, bool)
01198 {
01199     throw InternalErr(__FILE__, __LINE__, "Never use this method; see the programmer's guide documentation.");
01200     return sizeof(Sequence);
01201 }
01202 
01207 unsigned int
01208 Sequence::buf2val(void **)
01209 {
01210     throw InternalErr(__FILE__, __LINE__, "Use Sequence::var_value() or Sequence::row_value() in place of Sequence::buf2val()");
01211     return sizeof(Sequence);
01212 }
01213 
01214 void
01215 Sequence::print_one_row(FILE *out, int row, string space,
01216                         bool print_row_num)
01217 {
01218     if (print_row_num)
01219         fprintf(out, "\n%s%d: ", space.c_str(), row) ;
01220 
01221     fprintf(out, "{ ") ;
01222 
01223     int elements = element_count() - 1;
01224     int j;
01225     BaseType *bt_ptr;
01226     // Print first N-1 elements of the row.
01227     for (j = 0; j < elements; ++j) {
01228         bt_ptr = var_value(row, j);
01229         if (bt_ptr) {  // data
01230             if (bt_ptr->type() == dods_sequence_c)
01231                 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01232                 (out, space + "    ", false, print_row_num);
01233             else
01234                 bt_ptr->print_val(out, space, false);
01235             fprintf(out, ", ") ;
01236         }
01237     }
01238 
01239     // Print Nth element; end with a `}.'
01240     bt_ptr = var_value(row, j);
01241     if (bt_ptr) {  // data
01242         if (bt_ptr->type() == dods_sequence_c)
01243             dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01244             (out, space + "    ", false, print_row_num);
01245         else
01246             bt_ptr->print_val(out, space, false);
01247     }
01248 
01249     fprintf(out, " }") ;
01250 }
01251 
01252 void
01253 Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p,
01254                             bool print_row_numbers)
01255 {
01256     if (print_decl_p) {
01257         print_decl(out, space, false);
01258         fprintf(out, " = ") ;
01259     }
01260 
01261     fprintf(out, "{ ") ;
01262 
01263     int rows = number_of_rows() - 1;
01264     int i;
01265     for (i = 0; i < rows; ++i) {
01266         print_one_row(out, i, space, print_row_numbers);
01267         fprintf(out, ", ") ;
01268     }
01269     print_one_row(out, i, space, print_row_numbers);
01270 
01271     fprintf(out, " }") ;
01272 
01273     if (print_decl_p)
01274         fprintf(out, ";\n") ;
01275 }
01276 
01277 void
01278 Sequence::print_val(FILE *out, string space, bool print_decl_p)
01279 {
01280     print_val_by_rows(out, space, print_decl_p, false);
01281 }
01282 
01283 
01284 // print_all_vals is from Todd Karakasian.
01285 // We need to integrate this into print_val somehow, maybe by adding an XDR *
01286 // to Sequence? This can wait since print_val is mostly used for debugging...
01287 //
01288 // Deprecated. No longer needed since print_vals does its job.
01289 
01290 void
01291 Sequence::print_all_vals(FILE *out, XDR *, DDS *, string space,
01292                          bool print_decl_p)
01293 {
01294     print_val(out, space, print_decl_p);
01295 }
01296 
01297 bool
01298 Sequence::check_semantics(string &msg, bool all)
01299 {
01300     if (!BaseType::check_semantics(msg))
01301         return false;
01302 
01303     if (!unique_names(_vars, name(), type_name(), msg))
01304         return false;
01305 
01306     if (all)
01307         for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
01308             if (!(*i)->check_semantics(msg, true)) {
01309                 return false;
01310             }
01311         }
01312 
01313     return true;
01314 }
01315 
01316 void
01317 Sequence::set_leaf_p(bool state)
01318 {
01319     d_leaf_sequence = state;
01320 }
01321 
01322 bool
01323 Sequence::is_leaf_sequence()
01324 {
01325     return d_leaf_sequence;
01326 }
01327 
01352 void
01353 Sequence::set_leaf_sequence(int lvl)
01354 {
01355     bool has_child_sequence = false;
01356 
01357     if (lvl == 1) d_top_most = true;
01358 
01359     DBG2(cerr << "Processing sequence " << name() << endl);
01360 
01361     for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
01362         // About the test for send_p(): Only descend into a sequence if it has
01363         // fields that might be sent. Thus if, in a two-level sequence, nothing
01364         // in the lower level is to be sent, the upper level is marked as the
01365         // leaf sequence. This ensures that values _will_ be sent (see the comment
01366         // in serialize_leaf() and serialize_parent_part_one()).
01367         if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) {
01368             if (has_child_sequence)
01369                 throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator.");
01370 
01371             has_child_sequence = true;
01372             dynamic_cast<Sequence&>(**iter).set_leaf_sequence(++lvl);
01373         }
01374         else if ((*iter)->type() == dods_structure_c) {
01375             dynamic_cast<Structure&>(**iter).set_leaf_sequence(lvl);
01376         }
01377     }
01378 
01379     if (!has_child_sequence)
01380         set_leaf_p(true);
01381     else
01382         set_leaf_p(false);
01383 
01384     DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl);
01385 }
01386 
01395 void
01396 Sequence::dump(ostream &strm) const
01397 {
01398     strm << DapIndent::LMarg << "Sequence::dump - ("
01399     << (void *)this << ")" << endl ;
01400     DapIndent::Indent() ;
01401     Constructor::dump(strm) ;
01402     strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number
01403     << endl ;
01404     strm << DapIndent::LMarg << "bracket notation information:" << endl ;
01405     DapIndent::Indent() ;
01406     strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number
01407     << endl ;
01408     strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl ;
01409     strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number
01410     << endl ;
01411     DapIndent::UnIndent() ;
01412 
01413     strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl ;
01414     strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl ;
01415     strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence
01416     << endl ;
01417     strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most
01418     << endl ;
01419     DapIndent::UnIndent() ;
01420 }
01421 

Generated on Wed Jun 27 12:56:39 2007 for libdap++ by  doxygen 1.4.7