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

Generated on Wed Nov 14 03:15:44 2007 for libdap++ by  doxygen 1.5.1