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 
00156 Sequence::Sequence(const Sequence &rhs) : Constructor(rhs)
00157 {
00158     _duplicate(rhs);
00159 }
00160 
00161 BaseType *
00162 Sequence::ptr_duplicate()
00163 {
00164     return new Sequence(*this);
00165 }
00166 
00167 static inline void
00168 delete_bt(BaseType *bt_ptr)
00169 {
00170     DBG2(cerr << "In delete_bt: " << bt_ptr << endl);
00171     delete bt_ptr; bt_ptr = 0;
00172 }
00173 
00174 static inline void
00175 delete_rows(BaseTypeRow *bt_row_ptr)
00176 {
00177     DBG2(cerr << "In delete_rows: " << bt_row_ptr << endl);
00178 
00179     for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt);
00180 
00181     delete bt_row_ptr; bt_row_ptr = 0;
00182 }
00183 
00184 Sequence::~Sequence()
00185 {
00186     DBG2(cerr << "Entering Sequence::~Sequence" << endl);
00187     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00188         BaseType *btp = *i ;
00189         delete btp ; btp = 0;
00190     }
00191 
00192     for_each(d_values.begin(), d_values.end(), delete_rows);
00193     DBG2(cerr << "exiting Sequence::~Sequence" << endl);
00194 }
00195 
00196 Sequence &
00197 Sequence::operator=(const Sequence &rhs)
00198 {
00199     if (this == &rhs)
00200         return *this;
00201 
00202     dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
00203 
00204     _duplicate(rhs);
00205 
00206     return *this;
00207 }
00208 
00209 string
00210 Sequence::toString()
00211 {
00212     ostringstream oss;
00213 
00214     oss << BaseType::toString();
00215 
00216     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00217         oss << (*i)->toString();
00218     }
00219 
00220     oss << endl;
00221 
00222     return oss.str();
00223 }
00224 
00225 int
00226 Sequence::element_count(bool leaves)
00227 {
00228     if (!leaves)
00229         return _vars.size();
00230     else {
00231         int i = 0;
00232         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00233             i += (*iter)->element_count(true);
00234         }
00235         return i;
00236     }
00237 }
00238 
00239 bool
00240 Sequence::is_linear()
00241 {
00242     bool linear = true;
00243     bool seq_found = false;
00244     for (Vars_iter iter = _vars.begin(); linear && iter != _vars.end(); iter++) {
00245         if ((*iter)->type() == dods_sequence_c) {
00246             // A linear sequence cannot have more than one child seq. at any
00247             // one level. If we've already found a seq at this level, return
00248             // false.
00249             if (seq_found) {
00250                 linear = false;
00251                 break;
00252             }
00253             seq_found = true;
00254             linear = dynamic_cast<Sequence *>((*iter))->is_linear();
00255         }
00256         else if ((*iter)->type() == dods_structure_c) {
00257             linear = dynamic_cast<Structure*>((*iter))->is_linear();
00258         }
00259         else {
00260             // A linear sequence cannot have Arrays, Lists or Grids.
00261             linear = (*iter)->is_simple_type();
00262         }
00263     }
00264 
00265     return linear;
00266 }
00267 
00268 void
00269 Sequence::set_send_p(bool state)
00270 {
00271     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00272         (*i)->set_send_p(state);
00273     }
00274 
00275     BaseType::set_send_p(state);
00276 }
00277 
00278 void
00279 Sequence::set_read_p(bool state)
00280 {
00281     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00282         (*i)->set_read_p(state);
00283     }
00284 
00285     BaseType::set_read_p(state);
00286 }
00287 
00288 void
00289 Sequence::set_in_selection(bool state)
00290 {
00291     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00292         (*i)->set_in_selection(state);
00293     }
00294 
00295     BaseType::set_in_selection(state);
00296 }
00297 
00307 void
00308 Sequence::add_var(BaseType *bt, Part)
00309 {
00310     if (!bt)
00311         throw InternalErr(__FILE__, __LINE__,
00312                           "Cannot add variable: NULL pointer");
00313     // Jose Garcia
00314     // We append a copy of bt so the owner of bt is free to deallocate
00315 
00316     BaseType *bt_copy = bt->ptr_duplicate();
00317     bt_copy->set_parent(this);
00318     _vars.push_back(bt_copy);
00319 }
00320 
00321 // Deprecated
00322 BaseType *
00323 Sequence::var(const string &n, btp_stack &s)
00324 {
00325     string name = www2id(n);
00326 
00327     BaseType *btp = m_exact_match(name, &s);
00328     if (btp)
00329         return btp;
00330 
00331     return m_leaf_match(name, &s);
00332 }
00333 
00334 BaseType *
00335 Sequence::var(const string &name, bool exact_match, btp_stack *s)
00336 {
00337     string n = www2id(name);
00338 
00339     if (exact_match)
00340         return m_exact_match(n, s);
00341     else
00342         return m_leaf_match(n, s);
00343 }
00344 
00345 BaseType *
00346 Sequence::m_leaf_match(const string &name, btp_stack *s)
00347 {
00348     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00349         if ((*i)->name() == name) {
00350             if (s)
00351                 s->push(static_cast<BaseType *>(this));
00352             return *i;
00353         }
00354         if ((*i)->is_constructor_type()) {
00355             BaseType *btp = (*i)->var(name, false, s);
00356             if (btp) {
00357                 if (s)
00358                     s->push(static_cast<BaseType *>(this));
00359                 return btp;
00360             }
00361         }
00362     }
00363 
00364     return 0;
00365 }
00366 
00367 BaseType *
00368 Sequence::m_exact_match(const string &name, btp_stack *s)
00369 {
00370     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00371         if ((*i)->name() == name) {
00372             if (s)
00373                 s->push(static_cast<BaseType *>(this));
00374             return *i;
00375         }
00376     }
00377 
00378     string::size_type dot_pos = name.find("."); // zero-based index of `.'
00379     if (dot_pos != string::npos) {
00380         string aggregate = name.substr(0, dot_pos);
00381         string field = name.substr(dot_pos + 1);
00382 
00383         BaseType *agg_ptr = var(aggregate);
00384         if (agg_ptr) {
00385             if (s)
00386                 s->push(static_cast<BaseType *>(this));
00387             return agg_ptr->var(field, true, s); // recurse
00388         }
00389         else
00390             return 0;  // qualified names must be *fully* qualified
00391     }
00392 
00393     return 0;
00394 }
00395 
00400 BaseTypeRow *
00401 Sequence::row_value(size_t row)
00402 {
00403     if (row >= d_values.size())
00404         return 0;
00405     return d_values[row];
00406 }
00407 
00414 void
00415 Sequence::set_value(SequenceValues &values)
00416 {
00417     d_values = values;
00418 }
00419 
00422 SequenceValues
00423 Sequence::value()
00424 {
00425     return d_values;
00426 }
00427 
00433 BaseType *
00434 Sequence::var_value(size_t row, const string &name)
00435 {
00436     BaseTypeRow *bt_row_ptr = row_value(row);
00437     if (!bt_row_ptr)
00438         return 0;
00439 
00440     BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin();
00441     BaseTypeRow::iterator bt_row_end = bt_row_ptr->end();
00442     while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name)
00443         ++bt_row_iter;
00444 
00445     if (bt_row_iter == bt_row_end)
00446         return 0;
00447     else
00448         return *bt_row_iter;
00449 }
00450 
00456 BaseType *
00457 Sequence::var_value(size_t row, size_t i)
00458 {
00459     BaseTypeRow *bt_row_ptr = row_value(row);
00460     if (!bt_row_ptr)
00461         return 0;
00462 
00463     if (i >= bt_row_ptr->size())
00464         return 0;
00465 
00466     return (*bt_row_ptr)[i];
00467 }
00468 
00469 unsigned int
00470 Sequence::width()
00471 {
00472     unsigned int sz = 0;
00473 
00474     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00475         sz += (*i)->width();
00476     }
00477 
00478     return sz;
00479 }
00480 
00481 // This version returns -1. Each API-specific subclass should define a more
00482 // reasonable version. jhrg 5/24/96
00483 
00499 int
00500 Sequence::length()
00501 {
00502     return -1;
00503 }
00504 
00505 
00506 int
00507 Sequence::number_of_rows()
00508 {
00509     return d_values.size();
00510 }
00511 
00515 void
00516 Sequence::reset_row_number()
00517 {
00518     d_row_number = -1;
00519 }
00520 
00521 // Notes:
00522 // Assume that read() is implemented so that, when reading data for a nested
00523 // sequence, only the outer most level is *actually* read.
00524 // This is a consequence of our current (12/7/99) implementation of
00525 // the JGOFS server (which is the only server to actually use nested
00526 // sequences). 12/7/99 jhrg
00527 //
00528 // Stop assuming this. This logic is being moved into the JGOFS server
00529 // itself. 6/1/2001 jhrg
00530 
00531 // The read() function returns a boolean value, with TRUE
00532 // indicating that read() should be called again because there's
00533 // more data to read, and FALSE indicating there's no more data
00534 // to read. Note that this behavior is necessary to properly
00535 // handle variables that contain Sequences. Jose Garcia If an
00536 // error exists while reading, the implementers of the surrogate
00537 // library SHOULD throw an Error object which will propagate
00538 // beyond this point to to the original caller.
00539 // Jose Garcia
00540 
00575 bool
00576 Sequence::read_row(int row, const string &dataset, DDS &dds,
00577                    ConstraintEvaluator &eval, bool ce_eval)
00578 {
00579     DBG2(cerr << "Entering Sequence::read_row for " << name() << endl);
00580     if (row < d_row_number)
00581         throw InternalErr("Trying to back up inside a sequence!");
00582 
00583     DBG2(cerr << "read_row: row number " << row << ", current row " << d_row_number
00584          << endl);
00585     if (row == d_row_number)
00586         return true;
00587 
00588     dds.timeout_on();
00589 
00590     int eof = 0;  // Start out assuming EOF is false.
00591     while (!eof && d_row_number < row) {
00592         if (!read_p()) {
00593             eof = (read(dataset) == false);
00594         }
00595 
00596         // Advance the row number if ce_eval is false (we're not supposed to
00597         // evaluate the selection) or both ce_eval and the selection are
00598         // true.
00599         if (!eof && (!ce_eval || eval.eval_selection(dds, dataset)))
00600             d_row_number++;
00601 
00602         set_read_p(false); // ...so that the next instance will be read
00603     }
00604 
00605     // Once we finish the above loop, set read_p to true so that the caller
00606     // knows that data *has* been read. This is how the read() methods of the
00607     // elements of the sequence know to not call read() but instead look for
00608     // data values inside themselves.
00609     set_read_p(true);
00610 
00611     dds.timeout_off();
00612 
00613     // Return true if we have valid data, false if we've read to the EOF.
00614     return eof == 0;
00615 }
00616 
00617 // Private. This is used to process constraints on the rows of a sequence.
00618 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This
00619 // odd-looking logic first checks if d_ending_row_number is the sentinel
00620 // value of -1. If so, the sequence was not constrained by row number and
00621 // this method should never return true (which indicates that we're at the
00622 // end of a row-number constraint). If d_ending_row_number is not -1, then is
00623 // \e i at the end point? 6/1/2001 jhrg
00624 inline bool
00625 Sequence::is_end_of_rows(int i)
00626 {
00627     return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number));
00628 }
00629 
00690 bool
00691 Sequence::serialize(const string &dataset, ConstraintEvaluator &eval, DDS &dds,
00692                     Marshaller &m, bool ce_eval)
00693 {
00694     DBG2(cerr << "Entering Sequence::serialize for " << name() << endl);
00695 
00696     // Special case leaf sequences!
00697     if (is_leaf_sequence())
00698         return serialize_leaf(dataset, dds, eval, m, ce_eval);
00699     else
00700         return serialize_parent_part_one(dataset, dds, eval, m);
00701 }
00702 
00703 // We know this is not a leaf Sequence. That means that this Sequence holds
00704 // another Sequence as one of its fields _and_ that child Sequence triggers
00705 // the actual transmission of values.
00706 
00707 bool
00708 Sequence::serialize_parent_part_one(const string &dataset, DDS &dds,
00709                                     ConstraintEvaluator &eval, Marshaller &m)
00710 {
00711     DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl);
00712 
00713     int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
00714 
00715     // read_row returns true if valid data was read, false if the EOF was
00716     // found. 6/1/2001 jhrg
00717     // Since this is a parent sequence, read the row ignoring the CE (all of
00718     // the CE clauses will be evaluated by the leaf sequence).
00719     bool status = read_row(i, dataset, dds, eval, false);
00720     DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
00721 
00722     while (status && !is_end_of_rows(i)) {
00723         i += d_row_stride;
00724 
00725         // DBG(cerr << "Writing Start of Instance marker" << endl);
00726         // write_start_of_instance(sink);
00727 
00728         // In this loop serialize will signal an error with an exception.
00729         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00730             // Only call serialize for child Sequences; the leaf sequence
00731             // will trigger the transmission of values for its parents (this
00732             // sequence and maybe others) once it gets soem valid data to
00733             // send.
00734             // Note that if the leaf sequence has no variables in the current
00735             // projection, its serialize() method will never be called and that's
00736             // the method that triggers actually sending values. Thus the leaf
00737             // sequence must be the lowest level sequence with values whose send_p
00738             // property is true.
00739             if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c)
00740                 (*iter)->serialize(dataset, eval, dds, m);
00741         }
00742 
00743         set_read_p(false); // ...so this will read the next instance
00744 
00745         status = read_row(i, dataset, dds, eval, false);
00746         DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl);
00747     }
00748     // Reset current row number for next nested sequence element.
00749     d_row_number = -1;
00750 
00751     // Always write the EOS marker? 12/23/04 jhrg
00752     // Yes. According to DAP2, a completely empty response is signalled by
00753     // a return value of only the EOS marker for the outermost sequence.
00754     if (d_top_most || d_wrote_soi) {
00755         DBG(cerr << "Writing End of Sequence marker" << endl);
00756         write_end_of_sequence(m);
00757         d_wrote_soi = false;
00758     }
00759 
00760     return true;  // Signal errors with exceptions.
00761 }
00762 
00763 // If we are here then we know that this is 'parent sequence' and that the
00764 // leaf seq has found valid data to send. We also know that
00765 // serialize_parent_part_one has been called so data are in the instance's
00766 // fields. This is wheree we send data. Whereas ..._part_one() contains a
00767 // loop to iterate over all of rows in a parent sequence, this does not. This
00768 // method assumes that the serialize_leaf() will call it each time it needs
00769 // to be called.
00770 //
00771 // NB: This code only works if the child sequences appear after all other
00772 // variables.
00773 void
00774 Sequence::serialize_parent_part_two(const string &dataset, DDS &dds,
00775                                     ConstraintEvaluator &eval, Marshaller &m)
00776 {
00777     DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl);
00778 
00779     BaseType *btp = get_parent();
00780     if (btp && btp->type() == dods_sequence_c)
00781         dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dataset, dds,
00782                 eval, m);
00783 
00784     if (d_unsent_data) {
00785         DBG(cerr << "Writing Start of Instance marker" << endl);
00786         d_wrote_soi = true;
00787         write_start_of_instance(m);
00788 
00789         // In this loop serialize will signal an error with an exception.
00790         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00791             // Send all the non-sequence variables
00792             DBG(cerr << "Sequence::serialize_parent_part_two(), serializing "
00793                 << (*iter)->name() << endl);
00794             if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
00795                 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
00796                 (*iter)->serialize(dataset, eval, dds, m, false);
00797             }
00798         }
00799 
00800         d_unsent_data = false;              // read should set this.
00801     }
00802 }
00803 
00804 // This code is only run by a leaf sequence. Note that a one level sequence
00805 // is also a leaf sequence.
00806 bool
00807 Sequence::serialize_leaf(const string &dataset, DDS &dds,
00808                          ConstraintEvaluator &eval, Marshaller &m, bool ce_eval)
00809 {
00810     DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl);
00811     int i = (d_starting_row_number != -1) ? d_starting_row_number : 0;
00812 
00813     // read_row returns true if valid data was read, false if the EOF was
00814     // found. 6/1/2001 jhrg
00815     bool status = read_row(i, dataset, dds, eval, ce_eval);
00816     DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
00817 
00818     // Once the first valid (satisfies the CE) row of the leaf sequence has
00819     // been read, we know we're going to send data. Send the current instance
00820     // of the parent/ancestor sequences now, if there are any. We only need
00821     // to do this once, hence it's not inside the while loop, but we only
00822     // send the parent seq data _if_ there's data in the leaf to send, that's
00823     // why we wait until after the first call to read_row() here in the leaf
00824     // sequence.
00825     //
00826     // NB: It's important to only call serialize_parent_part_two() for a
00827     // Sequence that really is the parent of a leaf sequence. The fancy cast
00828     // will throw and exception if btp is not a Sequence, but doesn't test
00829     // that it's a parent sequence as we've defined them here.
00830     if (status && !is_end_of_rows(i)) {
00831         BaseType *btp = get_parent();
00832         if (btp && btp->type() == dods_sequence_c)
00833             dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dataset,
00834                     dds, eval, m);
00835     }
00836 
00837     d_wrote_soi = false;
00838     while (status && !is_end_of_rows(i)) {
00839         i += d_row_stride;
00840 
00841         DBG(cerr << "Writing Start of Instance marker" << endl);
00842         d_wrote_soi = true;
00843         write_start_of_instance(m);
00844 
00845         // In this loop serialize will signal an error with an exception.
00846         for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
00847             DBG(cerr << "Sequence::serialize_leaf(), serializing "
00848                 << (*iter)->name() << endl);
00849             if ((*iter)->send_p()) {
00850                 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl);
00851                 (*iter)->serialize(dataset, eval, dds, m, false);
00852             }
00853         }
00854 
00855         set_read_p(false); // ...so this will read the next instance
00856 
00857         status = read_row(i, dataset, dds, eval, ce_eval);
00858         DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl);
00859     }
00860 
00861     // Only write the EOS marker if there's a matching Start Of Instnace
00862     // Marker in the stream.
00863     if (d_wrote_soi || d_top_most) {
00864         DBG(cerr << "Writing End of Sequence marker" << endl);
00865         write_end_of_sequence(m);
00866     }
00867 
00868     return true;  // Signal errors with exceptions.
00869 }
00870 
00894 void
00895 Sequence::intern_data(const string &dataset, ConstraintEvaluator &eval, DDS &dds)
00896 {
00897     DBG(cerr << "Entering intern_data for " << name() << endl);
00898     DBG2(cerr << "    intern_data, values: " << &d_values << endl);
00899 
00900     // Why use a stack instead of return values? We need the stack because
00901     // Sequences neted three of more levels deep will loose the middle
00902     // instances when the intern_data_parent_part_two() code is run.
00903     sequence_values_stack_t sequence_values_stack;
00904     
00905     DBG2(cerr << "    pushing d_values (" << &d_values
00906          << ") on stack; size: " << sequence_values_stack.size() << endl);
00907     sequence_values_stack.push(&d_values);
00908 
00909     intern_data_private(dataset, eval, dds, sequence_values_stack);
00910 }
00911 
00912 void
00913 Sequence::intern_data_private(const string &dataset,
00914                                 ConstraintEvaluator &eval,
00915                                 DDS &dds,
00916                                 sequence_values_stack_t &sequence_values_stack)
00917 {
00918     DBG(cerr << "Entering intern_data_private for " << name() << endl);
00919 
00920     if (is_leaf_sequence())
00921         intern_data_for_leaf(dataset, dds, eval, sequence_values_stack);
00922     else
00923         intern_data_parent_part_one(dataset, dds, eval, sequence_values_stack);
00924 }
00925 
00926 void
00927 Sequence::intern_data_parent_part_one(const string & dataset, DDS & dds,
00928                                         ConstraintEvaluator & eval,
00929                                         sequence_values_stack_t &
00930                                         sequence_values_stack)
00931 {
00932     DBG(cerr << "Entering intern_data_parent_part_one for " << name() <<
00933         endl);
00934 
00935     int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
00936 
00937     // read_row returns true if valid data was read, false if the EOF was
00938     // found. 6/1/2001 jhrg
00939     // Since this is a parent sequence, read the row ignoring the CE (all of
00940     // the CE clauses will be evaluated by the leaf sequence).
00941     bool status = read_row(i, dataset, dds, eval, false);
00942 
00943     while (status
00944            && (get_ending_row_number() == -1
00945                || i <= get_ending_row_number())) {
00946         i += get_row_stride();
00947         for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
00948             if ((*iter)->send_p()) {
00949                 switch ((*iter)->type()) {
00950                 case dods_sequence_c:
00951                     dynamic_cast<Sequence&>(**iter).intern_data_private(dataset,
00952                             eval, dds, sequence_values_stack);
00953                     break;
00954 
00955                 default:
00956                     (*iter)->intern_data(dataset, eval, dds);
00957                     break;
00958                 }
00959             }
00960         }
00961 
00962         set_read_p(false);      // ...so this will read the next instance
00963 
00964         status = read_row(i, dataset, dds, eval, false);
00965     }
00966 
00967     // Reset current row number for next nested sequence element.
00968     reset_row_number();
00969     DBG2(cerr << "    popping d_values (" << sequence_values_stack.top()
00970          << ") off stack; size: " << sequence_values_stack.size() << endl);
00971     sequence_values_stack.pop();
00972 }
00973 
00974 void
00975 Sequence::intern_data_parent_part_two(const string &dataset, DDS &dds,
00976                                       ConstraintEvaluator &eval,
00977                                       sequence_values_stack_t &sequence_values_stack)
00978 {
00979     DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl);
00980 
00981     BaseType *btp = get_parent();
00982     if (btp && btp->type() == dods_sequence_c) {
00983         dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two(dataset, 
00984                                       dds, eval, sequence_values_stack);
00985     }
00986 
00987     DBG2(cerr << "    stack size: " << sequence_values_stack.size() << endl);
00988     SequenceValues *values = sequence_values_stack.top();
00989     DBG2(cerr << "    using values = " << values << endl);
00990 
00991     if (get_unsent_data()) {
00992         BaseTypeRow *row_data = new BaseTypeRow;
00993 
00994         // In this loop transfer_data will signal an error with an exception.
00995         for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
00996 
00997             if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) {
00998                 row_data->push_back((*iter)->ptr_duplicate());
00999             }
01000             else if ((*iter)->send_p()) { //Sequence; must be the last variable
01001                 Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate());
01002                 row_data->push_back(tmp);
01003                 DBG2(cerr << "    pushing d_values (" << &(dynamic_cast<Sequence&>(*tmp).d_values)
01004                      << ") on stack; size: " << sequence_values_stack.size() << endl);
01005                 // This pushes the d_values field of the newly created leaf 
01006                 // Sequence onto the stack. The code then returns to intern
01007                 // _data_for_leaf() where this value will be used.
01008                 sequence_values_stack.push(&(dynamic_cast<Sequence&>(*tmp).d_values));
01009             }
01010         }
01011 
01012         DBG2(cerr << "    pushing values for " << name() << " to " << values << endl);
01013         values->push_back(row_data);
01014         set_unsent_data(false);
01015     }
01016 }
01017 
01018 void
01019 Sequence::intern_data_for_leaf(const string &dataset, DDS &dds,
01020                                ConstraintEvaluator &eval,
01021                                sequence_values_stack_t &sequence_values_stack)
01022 {
01023     DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl);
01024     
01025     int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0;
01026 
01027     DBG2(cerr << "    reading row " << i << endl);
01028     bool status = read_row(i, dataset, dds, eval, true);
01029     DBG2(cerr << "    status: " << status << endl);
01030     
01031     if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) {
01032         BaseType *btp = get_parent();
01033         if (btp && btp->type() == dods_sequence_c) {
01034             // This call will read the values for the parent sequences and 
01035             // then allocate a new instance for the leaf and push that onto
01036             // the stack.
01037             dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two(dataset,
01038                 dds, eval, sequence_values_stack);
01039         }
01040 
01041         // intern_data_parent_part_two pushes the d_values field of the leaf
01042         // onto the stack, so this operation grabs that value and then loads
01043         // data into it.
01044         SequenceValues *values = sequence_values_stack.top();
01045         DBG2(cerr << "    using values = " << values << endl);
01046 
01047         while (status && (get_ending_row_number() == -1 
01048                           || i <= get_ending_row_number())) {
01049             i += get_row_stride();
01050 
01051             // Copy data from the object's fields to this new BaeTypeRow instance
01052             BaseTypeRow *row_data = new BaseTypeRow;
01053             for (Vars_iter iter = var_begin(); iter != var_end(); iter++) {
01054                 if ((*iter)->send_p()) {
01055                     row_data->push_back((*iter)->ptr_duplicate());
01056                 }
01057             }
01058 
01059             DBG2(cerr << "    pushing values for " << name() << " to " << values << endl);
01060             // Save the row_data to values().
01061             values->push_back(row_data);
01062             
01063             set_read_p(false);      // ...so this will read the next instance
01064             // Read the ith row into this object's fields
01065             status = read_row(i, dataset, dds, eval, true);
01066         }
01067 
01068         DBG2(cerr << "    popping d_values (" << sequence_values_stack.top()
01069              << ") off stack; size: " << sequence_values_stack.size() << endl);
01070         sequence_values_stack.pop();
01071     }
01072 }
01073 
01094 bool
01095 Sequence::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
01096 {
01097     DataDDS *dd = dynamic_cast<DataDDS *>(dds);
01098     if (!dd)
01099         throw InternalErr("Expected argument 'dds' to be a DataDDS!");
01100 
01101     DBG2(cerr << "Reading from server/protocol version: "
01102          << dd->get_protocol_major() << "." << dd->get_protocol_minor()
01103          << endl);
01104 
01105     // Check for old servers.
01106     if (dd->get_protocol_major() < 2) {
01107         throw Error(string("The protocl version (") + dd->get_protocol() 
01108                     + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator.");
01109     }
01110 
01111     while (true) {
01112         // Grab the sequence stream's marker.
01113         unsigned char marker = read_marker(um);
01114         if (is_end_of_sequence(marker))
01115             break;  // EXIT the while loop here!!!
01116         else if (is_start_of_instance(marker)) {
01117             d_row_number++;
01118             DBG2(cerr << "Reading row " << d_row_number << " of "
01119                  << name() << endl);
01120             BaseTypeRow *bt_row_ptr = new BaseTypeRow;
01121             // Read the instance's values, building up the row
01122             for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
01123                 BaseType *bt_ptr = (*iter)->ptr_duplicate();
01124                 bt_ptr->deserialize(um, dds, reuse);
01125                 DBG2(cerr << "Deserialized " << bt_ptr->name() << " ("
01126                      << bt_ptr << ") = ");
01127                 DBG2(bt_ptr->print_val(stderr, ""));
01128                 bt_row_ptr->push_back(bt_ptr);
01129             }
01130             // Append this row to those accumulated.
01131             d_values.push_back(bt_row_ptr);
01132         }
01133         else
01134             throw Error("I could not read the expected Sequence data stream marker!");
01135     };
01136 
01137     return false;
01138 }
01139 
01140 // Return the current row number.
01141 
01153 int
01154 Sequence::get_starting_row_number()
01155 {
01156     return d_starting_row_number;
01157 }
01158 
01169 int
01170 Sequence::get_row_stride()
01171 {
01172     return d_row_stride;
01173 }
01174 
01186 int
01187 Sequence::get_ending_row_number()
01188 {
01189     return d_ending_row_number;
01190 }
01191 
01200 void
01201 Sequence::set_row_number_constraint(int start, int stop, int stride)
01202 {
01203     if (stop < start)
01204         throw Error(malformed_expr, "Starting row number must precede the ending row number.");
01205 
01206     d_starting_row_number = start;
01207     d_row_stride = stride;
01208     d_ending_row_number = stop;
01209 }
01210 
01213 unsigned int
01214 Sequence::val2buf(void *, bool)
01215 {
01216     throw InternalErr(__FILE__, __LINE__, "Never use this method; see the programmer's guide documentation.");
01217     return sizeof(Sequence);
01218 }
01219 
01224 unsigned int
01225 Sequence::buf2val(void **)
01226 {
01227     throw InternalErr(__FILE__, __LINE__, "Use Sequence::var_value() or Sequence::row_value() in place of Sequence::buf2val()");
01228     return sizeof(Sequence);
01229 }
01230 
01231 void
01232 Sequence::print_one_row(FILE *out, int row, string space,
01233                         bool print_row_num)
01234 {
01235     if (print_row_num)
01236         fprintf(out, "\n%s%d: ", space.c_str(), row) ;
01237 
01238     fprintf(out, "{ ") ;
01239 
01240     int elements = element_count() - 1;
01241     int j;
01242     BaseType *bt_ptr;
01243     // Print first N-1 elements of the row.
01244     for (j = 0; j < elements; ++j) {
01245         bt_ptr = var_value(row, j);
01246         if (bt_ptr) {  // data
01247             if (bt_ptr->type() == dods_sequence_c)
01248                 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01249                 (out, space + "    ", false, print_row_num);
01250             else
01251                 bt_ptr->print_val(out, space, false);
01252             fprintf(out, ", ") ;
01253         }
01254     }
01255 
01256     // Print Nth element; end with a `}.'
01257     bt_ptr = var_value(row, j);
01258     if (bt_ptr) {  // data
01259         if (bt_ptr->type() == dods_sequence_c)
01260             dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01261             (out, space + "    ", false, print_row_num);
01262         else
01263             bt_ptr->print_val(out, space, false);
01264     }
01265 
01266     fprintf(out, " }") ;
01267 }
01268 
01269 void
01270 Sequence::print_one_row(ostream &out, int row, string space,
01271                         bool print_row_num)
01272 {
01273     if (print_row_num)
01274         out << "\n" << space << row << ": " ;
01275 
01276     out << "{ " ;
01277 
01278     int elements = element_count();
01279     int j = 0;
01280     BaseType *bt_ptr = 0;
01281     
01282     // This version of print_one_row() works for both data read with 
01283     // deserialize(), where each variable is assumed to have valid data, and
01284     // intern_data(), where some/many variables do not. Because of that, it's
01285     // not correct to assume that all of the elements will be printed, which 
01286     // is what the old code did.
01287     // Print the first value
01288     while (j < elements && !bt_ptr) {
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         }
01297     }
01298 
01299     // Print the remaining values
01300     while (j < elements) {
01301         bt_ptr = var_value(row, j++);
01302         if (bt_ptr) {  // data
01303             out << ", ";
01304             if (bt_ptr->type() == dods_sequence_c)
01305                 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01306                         (out, space + "    ", false, print_row_num);
01307             else
01308                 bt_ptr->print_val(out, space, false);
01309         }
01310     }
01311     
01312 #if 0
01313     // old version
01314     int elements = element_count() - 1;
01315     int j;
01316     BaseType *bt_ptr;
01317     // Print first N-1 elements of the row.
01318     for (j = 0; j < elements; ++j) {
01319         bt_ptr = var_value(row, j);
01320         if (bt_ptr) {  // data
01321             if (bt_ptr->type() == dods_sequence_c)
01322                 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01323                      (out, space + "    ", false, print_row_num);
01324             else
01325                 bt_ptr->print_val(out, space, false);
01326             out << ", " ;
01327         }
01328     }
01329 
01330     // Print Nth element; end with a `}.'
01331     bt_ptr = var_value(row, j);
01332     if (bt_ptr) {  // data
01333         if (bt_ptr->type() == dods_sequence_c)
01334             dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows
01335             (out, space + "    ", false, print_row_num);
01336         else
01337             bt_ptr->print_val(out, space, false);
01338     }
01339 #endif
01340 
01341     out << " }" ;
01342 }
01343 
01344 void
01345 Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p,
01346                             bool print_row_numbers)
01347 {
01348     if (print_decl_p) {
01349         print_decl(out, space, false);
01350         fprintf(out, " = ") ;
01351     }
01352 
01353     fprintf(out, "{ ") ;
01354 
01355     int rows = number_of_rows() - 1;
01356     int i;
01357     for (i = 0; i < rows; ++i) {
01358         print_one_row(out, i, space, print_row_numbers);
01359         fprintf(out, ", ") ;
01360     }
01361     print_one_row(out, i, space, print_row_numbers);
01362 
01363     fprintf(out, " }") ;
01364 
01365     if (print_decl_p)
01366         fprintf(out, ";\n") ;
01367 }
01368 
01369 void
01370 Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p,
01371                             bool print_row_numbers)
01372 {
01373     if (print_decl_p) {
01374         print_decl(out, space, false);
01375         out << " = " ;
01376     }
01377 
01378     out << "{ " ;
01379 
01380     int rows = number_of_rows() - 1;
01381     int i;
01382     for (i = 0; i < rows; ++i) {
01383         print_one_row(out, i, space, print_row_numbers);
01384         out << ", " ;
01385     }
01386     print_one_row(out, i, space, print_row_numbers);
01387 
01388     out << " }" ;
01389 
01390     if (print_decl_p)
01391         out << ";\n" ;
01392 }
01393 
01394 void
01395 Sequence::print_val(FILE *out, string space, bool print_decl_p)
01396 {
01397     print_val_by_rows(out, space, print_decl_p, false);
01398 }
01399 
01400 void
01401 Sequence::print_val(ostream &out, string space, bool print_decl_p)
01402 {
01403     print_val_by_rows(out, space, print_decl_p, false);
01404 }
01405 
01406 
01407 bool
01408 Sequence::check_semantics(string &msg, bool all)
01409 {
01410     if (!BaseType::check_semantics(msg))
01411         return false;
01412 
01413     if (!unique_names(_vars, name(), type_name(), msg))
01414         return false;
01415 
01416     if (all)
01417         for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
01418             if (!(*i)->check_semantics(msg, true)) {
01419                 return false;
01420             }
01421         }
01422 
01423     return true;
01424 }
01425 
01426 void
01427 Sequence::set_leaf_p(bool state)
01428 {
01429     d_leaf_sequence = state;
01430 }
01431 
01432 bool
01433 Sequence::is_leaf_sequence()
01434 {
01435     return d_leaf_sequence;
01436 }
01437 
01462 void
01463 Sequence::set_leaf_sequence(int lvl)
01464 {
01465     bool has_child_sequence = false;
01466 
01467     if (lvl == 1) d_top_most = true;
01468 
01469     DBG2(cerr << "Processing sequence " << name() << endl);
01470 
01471     for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) {
01472         // About the test for send_p(): Only descend into a sequence if it has
01473         // fields that might be sent. Thus if, in a two-level sequence, nothing
01474         // in the lower level is to be sent, the upper level is marked as the
01475         // leaf sequence. This ensures that values _will_ be sent (see the comment
01476         // in serialize_leaf() and serialize_parent_part_one()).
01477         if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) {
01478             if (has_child_sequence)
01479                 throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator.");
01480 
01481             has_child_sequence = true;
01482             dynamic_cast<Sequence&>(**iter).set_leaf_sequence(++lvl);
01483         }
01484         else if ((*iter)->type() == dods_structure_c) {
01485             dynamic_cast<Structure&>(**iter).set_leaf_sequence(lvl);
01486         }
01487     }
01488 
01489     if (!has_child_sequence)
01490         set_leaf_p(true);
01491     else
01492         set_leaf_p(false);
01493 
01494     DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl);
01495 }
01496 
01505 void
01506 Sequence::dump(ostream &strm) const
01507 {
01508     strm << DapIndent::LMarg << "Sequence::dump - ("
01509     << (void *)this << ")" << endl ;
01510     DapIndent::Indent() ;
01511     Constructor::dump(strm) ;
01512     strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number
01513          << endl ;
01514     strm << DapIndent::LMarg << "bracket notation information:" << endl ;
01515     DapIndent::Indent() ;
01516     strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number
01517          << endl ;
01518     strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl ;
01519     strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number
01520          << endl ;
01521     DapIndent::UnIndent() ;
01522 
01523     strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl ;
01524     strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl ;
01525     strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence
01526          << endl ;
01527     strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most
01528          << endl ;
01529     DapIndent::UnIndent() ;
01530 }
01531 
01532 } // namespace libdap
01533 

Generated on Tue Jun 10 18:00:31 2008 for libdap++ by  doxygen 1.5.4