DDS.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 //
00032 // jhrg 9/7/94
00033 
00034 #include "config.h"
00035 
00036 static char rcsid[] not_used =
00037     {"$Id: DDS.cc 22560 2010-04-21 21:22:00Z jimg $"
00038     };
00039 
00040 #include <cstdio>
00041 #include <sys/types.h>
00042 
00043 #ifdef WIN32
00044 #include <io.h>
00045 #include <process.h>
00046 #include <fstream>
00047 #else
00048 #include <unistd.h>    // for alarm and dup
00049 #include <sys/wait.h>
00050 #endif
00051 
00052 #include <iostream>
00053 #include <sstream>
00054 #include <algorithm>
00055 #include <functional>
00056 
00057 //#define DODS_DEBUG
00058 //#define DODS_DEBUG2
00059 
00060 #include "GNURegex.h"
00061 
00062 #include "DAS.h"
00063 #include "Clause.h"
00064 #include "Error.h"
00065 #include "InternalErr.h"
00066 
00067 #include "parser.h"
00068 #include "debug.h"
00069 #include "util.h"
00070 
00071 #include "Byte.h"
00072 #include "Int16.h"
00073 #include "UInt16.h"
00074 #include "Int32.h"
00075 #include "UInt32.h"
00076 #include "Float32.h"
00077 #include "Float64.h"
00078 #include "Str.h"
00079 #include "Url.h"
00080 #include "Array.h"
00081 #include "Structure.h"
00082 #include "Sequence.h"
00083 #include "Grid.h"
00084 
00085 #include "escaping.h"
00086 
00087 const string c_default_dap20_schema_location = "http://xml.opendap.org/dap/dap2.xsd";
00088 const string c_default_dap32_schema_location = "http://xml.opendap.org/dap/dap3.2.xsd";
00089 
00090 const string c_dap20_namespace = "http://xml.opendap.org/ns/DAP2";
00091 const string c_dap32_namespace = "http://xml.opendap.org/ns/DAP/3.2#";
00092 
00093 const string grddl_transformation_dap32 = "http://xml.opendap.org/transforms/ddxToRdfTriples.xsl";
00094 
00095 const string c_xml_namespace = "http://www.w3.org/XML/1998/namespace";
00096 
00097 using namespace std;
00098 
00099 void ddsrestart(FILE *yyin); // Defined in dds.tab.c
00100 int ddsparse(void *arg);
00101 
00102 // Glue for the DDS parser defined in dds.lex
00103 void dds_switch_to_buffer(void *new_buffer);
00104 void dds_delete_buffer(void * buffer);
00105 void *dds_buffer(FILE *fp);
00106 
00107 namespace libdap {
00108 
00109 void
00110 DDS::duplicate(const DDS &dds)
00111 {
00112     DBG(cerr << "Entering DDS::duplicate... " <<endl);
00113     name = dds.name;
00114     d_filename = dds.d_filename;
00115     d_container_name = dds.d_container_name;
00116     d_timeout = dds.d_timeout;
00117     d_attr = dds.d_attr;
00118 
00119     d_factory = dds.d_factory;
00120     d_container = dds.d_container;
00121     d_dap_major = dds.d_dap_major;
00122     d_dap_minor = dds.d_dap_minor;
00123 
00124     DDS &dds_tmp = const_cast<DDS &>(dds);
00125 
00126     // copy the things pointed to by the list, not just the pointers
00127     for (Vars_iter i = dds_tmp.var_begin(); i != dds_tmp.var_end(); i++) {
00128         add_var(*i); // add_var() dups the BaseType.
00129     }
00130 }
00131 
00142 DDS::DDS(BaseTypeFactory *factory, const string &n)
00143 
00144         : d_factory(factory), name(n), d_container(0), d_dap_major(2),
00145         d_dap_minor(0),
00146         d_request_xml_base(""), d_timeout(0)
00147 {
00148     DBG(cerr << "Building a DDS with client major/minor: "
00149             << d_dap_major << "." << d_dap_minor << endl);
00150 }
00151 
00153 DDS::DDS(const DDS &rhs) : DapObj()
00154 {
00155     DBG(cerr << "Entering DDS(const DDS &rhs) ..." << endl);
00156     duplicate(rhs);
00157     DBG(cerr << " bye." << endl);
00158 }
00159 
00160 DDS::~DDS()
00161 {
00162     // delete all the variables in this DDS
00163     for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
00164         BaseType *btp = *i ;
00165         delete btp ; btp = 0;
00166     }
00167 }
00168 
00169 DDS &
00170 DDS::operator=(const DDS &rhs)
00171 {
00172     DBG(cerr << "Entering DDS::operator= ..." << endl);
00173     if (this == &rhs)
00174         return *this;
00175 
00176     duplicate(rhs);
00177 
00178     DBG(cerr << " bye." << endl);
00179     return *this;
00180 }
00181 
00182 #if 0
00183 
00198 BaseType *
00199 DDS::find_hdf4_dimension_attribute_home(AttrTable::entry *source)
00200 {
00201     BaseType *btp;
00202     string::size_type i = source->name.find("_dim_");
00203     if (i != string::npos && (btp = var(source->name.substr(0, i)))) {
00204         if (btp->is_vector_type()) {
00205             return btp;
00206         }
00207         else if (btp->type() == dods_grid_c) {
00208             // For a Grid, the hdf4 handler uses _dim_n for the n-th Map
00209             // i+5 points to the character holding 'n'
00210             int n = atoi(source->name.substr(i + 5).c_str());
00211             DBG(cerr << "Found a Grid (" << btp->name() << ") and "
00212                 << source->name.substr(i) << ", extracted n: " << n << endl);
00213             return *(dynamic_cast<Grid&>(*btp).map_begin() + n);
00214         }
00215     }
00216 
00217     return 0;
00218 }
00219 
00225 AttrTable *
00226 DDS::find_matching_container(AttrTable::entry *source, BaseType **dest_variable)
00227 {
00228     // The attribute entry 'source' must be a container
00229     if (source->type != Attr_container)
00230         throw InternalErr(__FILE__, __LINE__, "DDS::find_matching_container; expected 'source' to be a container.");
00231 
00232     // Use the name of the attribute container 'source' to figure out where
00233     // to put its contents.
00234     BaseType *btp;
00235     if ((btp = var(source->name))) {
00236         // ... matches a variable name? Use var's table
00237         *dest_variable = btp;
00238         return &btp->get_attr_table();
00239     }
00240     else if ((btp = find_hdf4_dimension_attribute_home(source))) {
00241         // ... hdf4 dimension attribute? Make a sub table and use that.
00242         // btp can only be an Array or a Grid Map (which is an array)
00243         if (btp->get_parent() && btp->get_parent()->type() == dods_grid_c) {
00244             DBG(cerr << "Found a Grid, assigning to the map" << endl);
00245             *dest_variable = btp;
00246             return &btp->get_attr_table();
00247         }
00248         else { // must be a plain Array
00249             string::size_type i = source->name.find("_dim_");
00250             string ext = source->name.substr(i + 1);
00251             *dest_variable = btp;
00252             return btp->get_attr_table().append_container(ext);
00253         }
00254     }
00255     else {
00256         // ... otherwise assume it's a global attribute.
00257         AttrTable *at = d_attr.find_container(source->name);
00258         if (!at) {
00259             at = new AttrTable();       // Make a new global table if needed
00260             d_attr.append_container(at, source->name);
00261         }
00262 
00263         *dest_variable = 0;
00264         return at;
00265     }
00266 }
00267 
00289 void
00290 DDS::transfer_attributes(DAS *das)
00291 {
00292     // If there is a container set in the DDS then get the container from
00293     // the DAS. If they are not the same container, then throw an exception
00294     // (should be working on the same container). If the container does not
00295     // exist in the DAS, then throw an exception
00296     if( d_container )
00297     {
00298         if( das->container_name() != d_container_name )
00299         {
00300             string err = (string)"Error transferring attributes: "
00301                          + "working on container in dds, but not das" ;
00302             throw InternalErr(__FILE__, __LINE__, err ) ;
00303         }
00304     }
00305 
00306     AttrTable *top_level = das->get_top_level_attributes() ;
00307 
00308     // foreach container at the outer level
00309     AttrTable::Attr_iter das_i = top_level->attr_begin();
00310     AttrTable::Attr_iter das_e = top_level->attr_end();
00311     while (das_i != das_e) {
00312         DBG(cerr << "Working on the '" << (*das_i)->name << "' container."
00313             << endl);
00314 
00315         AttrTable *source = (*das_i)->attributes;
00316         // Variable that holds 'dest'; null for a global attribute.
00317         BaseType *dest_variable = 0;
00318         AttrTable *dest = find_matching_container(*das_i, &dest_variable);
00319 
00320         // foreach source attribute in the das_i container
00321         AttrTable::Attr_iter source_p = source->attr_begin();
00322         while (source_p != source->attr_end()) {
00323             DBG(cerr << "Working on the '" << (*source_p)->name << "' attribute"
00324                 << endl);
00325 
00326             // If this is an attribute container, we must have a container
00327             // (this one) within a container (the 'source'). Look and see if
00328             // the variable is a Constructor. If so, pass that container into
00329             // Constructor::transfer_attributes()
00330             if ((*source_p)->type == Attr_container) {
00331                 if (dest_variable && dest_variable->is_constructor_type()) {
00332                     dynamic_cast<Constructor&>(*dest_variable).transfer_attributes(*source_p);
00333                 }
00334                 else {
00335                     dest->append_container(new AttrTable(*(*source_p)->attributes),
00336                                            (*source_p)->name);
00337                 }
00338             }
00339             else {
00340                 dest->append_attr(source->get_name(source_p),
00341                                   source->get_type(source_p),
00342                                   source->get_attr_vector(source_p));
00343             }
00344 
00345             ++source_p;
00346         }
00347 
00348         ++das_i;
00349     }
00350 }
00351 #endif
00352 
00366 void
00367 DDS::transfer_attributes(DAS *das)
00368 {
00369     // If there is a container set in the DDS then get the container from
00370     // the DAS. If they are not the same container, then throw an exception
00371     // (should be working on the same container). If the container does not
00372     // exist in the DAS, then throw an exception
00373     if( d_container )
00374     {
00375         if( das->container_name() != d_container_name )
00376             throw InternalErr(__FILE__, __LINE__, "Error transferring attributes: working on a container in dds, but not das" ) ;
00377     }
00378 
00379     // Give each variable a chance to claim its attributes.
00380     AttrTable *top_level = das->get_top_level_attributes() ;
00381 
00382     Vars_iter var = var_begin();
00383     while (var != var_end()) {
00384         (*var)->transfer_attributes(top_level);
00385         var++;
00386     }
00387 
00388     // Now we transfer all of the attributes still marked as global to the
00389     // global container in the DDS.
00390 
00391     AttrTable::Attr_iter at_cont_p = top_level->attr_begin();
00392     while (at_cont_p != top_level->attr_end()) {
00393         // In truth, all of the top level attributes should be containers, but
00394         // this test handles the abnormal case where somehow someone makes a
00395         // top level attribute that is not a container by silently dropping it.
00396         if ((*at_cont_p)->type == Attr_container
00397                 && (*at_cont_p)->attributes->is_global_attribute()) {
00398             DBG(cerr << (*at_cont_p)->name << " is a global attribute." << endl);
00399             // copy the source container so that the DAS passed in can be
00400             // deleted after calling htis method.
00401             AttrTable *at = new AttrTable(*(*at_cont_p)->attributes);
00402             d_attr.append_container(at, at->get_name());
00403         }
00404 
00405         at_cont_p++;
00406     }
00407 }
00408 
00409 #if 0
00410     // cruft from the above method
00411 
00412             AttrTable *dest = d_attr.find_container(at->get_name());
00413             if (!dest) {
00414                 cerr << "making a new sub containter for it" << endl;
00415                 // If there's currently no top level container with this
00416                 //container's name (the typical case) make one.
00417                 dest = new AttrTable(); // Make a new global table if needed
00418                 d_attr.append_container(dest, at->get_name());
00419             }
00420 
00421             cerr << "now copying its contents to the new container" << endl;
00422             // Now copy all of the global attribute's stuff into the matching
00423             // container in the DDS.
00424             AttrTable::Attr_iter at_p = at->attr_begin();
00425             while (at_p != at->attr_end()) {
00426                 if (at->get_attr_type(at_p) == Attr_container)
00427                     dest->append_container(at->get_attr_table(at_p), at->get_name(at_p));
00428                 else
00429                     dest->append_attr(at->get_name(at_p), at->get_type(at_p), at->get_attr_vector(at_p));
00430                 at_p++;
00431             }
00432 #endif
00433 
00441 
00443 string
00444 DDS::get_dataset_name() const
00445 {
00446     return name;
00447 }
00448 
00450 void
00451 DDS::set_dataset_name(const string &n)
00452 {
00453     name = n;
00454 }
00455 
00457 
00459 AttrTable &
00460 DDS::get_attr_table()
00461 {
00462     return d_attr;
00463 }
00464 
00474 string
00475 DDS::filename()
00476 {
00477     return d_filename;
00478 }
00479 
00481 void
00482 DDS::filename(const string &fn)
00483 {
00484     d_filename = fn;
00485 }
00487 
00493 void
00494 DDS::set_dap_version(const string &version_string)
00495 {
00496     istringstream iss(version_string);
00497 
00498     int major = -1, minor = -1;
00499     char dot;
00500     iss >> major;
00501     iss >> dot;
00502     iss >> minor;
00503 
00504     DBG(cerr << "Major: " << major << ", dot: " << dot <<", Minor: " << minor << endl);
00505 
00506     if (major == -1 || minor == -1)
00507         throw Error("Could not parse the client dap (XDAP-Accept header) value");
00508 
00509     set_dap_major(major);
00510     set_dap_minor(minor);
00511 }
00512 
00522 string
00523 DDS::container_name()
00524 {
00525     return d_container_name;
00526 }
00527 
00530 void
00531 DDS::container_name(const string &cn)
00532 {
00533     // we want to search the DDS for the top level structure with the given
00534     // name. Set the container to null so that we don't search some previous
00535     // container.
00536     d_container = 0 ;
00537     if( !cn.empty() )
00538     {
00539         d_container = dynamic_cast<Structure *>( var( cn ) ) ;
00540         if( !d_container )
00541         {
00542             // create a structure for this container. Calling add_var
00543             // while_container is null will add the new structure to DDS and
00544             // not some sub structure. Adding the new structure makes a copy
00545             // of it.  So after adding it, go get it and set d_container.
00546             Structure *s = new Structure( cn ) ;
00547             add_var( s ) ;
00548             delete s ;
00549             s = 0 ;
00550             d_container = dynamic_cast<Structure *>( var( cn ) ) ;
00551         }
00552     }
00553     d_container_name = cn;
00554 
00555 }
00556 
00558 Structure *
00559 DDS::container()
00560 {
00561     return d_container ;
00562 }
00563 
00565 
00571 void
00572 DDS::add_var(BaseType *bt)
00573 {
00574     if (!bt)
00575         throw InternalErr(__FILE__, __LINE__,
00576                           "Trying to add a BaseType object with a NULL pointer.");
00577 
00578     DBG2(cerr << "In DDS::add_var(), bt's address is: " << bt << endl);
00579 
00580     BaseType *btp = bt->ptr_duplicate();
00581     DBG2(cerr << "In DDS::add_var(), btp's address is: " << btp << endl);
00582     if( d_container )
00583     {
00584         // Mem leak fix [mjohnson nov 2009]
00585         // Structure::add_var() creates ANOTHER copy.
00586         d_container->add_var( bt ) ;
00587         // So we need to delete btp or else it leaks
00588         delete btp; btp = 0;
00589     }
00590     else
00591     {
00592         vars.push_back(btp);
00593     }
00594 }
00595 
00602 void
00603 DDS::del_var(const string &n)
00604 {
00605     if( d_container )
00606     {
00607         d_container->del_var( n ) ;
00608         return ;
00609     }
00610 
00611     for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
00612         if ((*i)->name() == n) {
00613             BaseType *bt = *i ;
00614             vars.erase(i) ;
00615             delete bt ; bt = 0;
00616             return;
00617         }
00618     }
00619 }
00620 
00625 void
00626 DDS::del_var(Vars_iter i)
00627 {
00628     if (i != vars.end()) {
00629         BaseType *bt = *i ;
00630         vars.erase(i) ;
00631         delete bt ; bt = 0;
00632     }
00633 }
00634 
00641 void
00642 DDS::del_var(Vars_iter i1, Vars_iter i2)
00643 {
00644     for (Vars_iter i_tmp = i1; i_tmp != i2; i_tmp++) {
00645         BaseType *bt = *i_tmp ;
00646         delete bt ; bt = 0;
00647     }
00648     vars.erase(i1, i2) ;
00649 }
00650 
00658 BaseType *
00659 DDS::var(const string &n, BaseType::btp_stack &s)
00660 {
00661     return var(n, &s);
00662 }
00682 BaseType *
00683 DDS::var(const string &n, BaseType::btp_stack *s)
00684 {
00685     string name = www2id(n);
00686     if( d_container )
00687         return d_container->var( name, false, s ) ;
00688 
00689     BaseType *v = exact_match(name, s);
00690     if (v)
00691         return v;
00692 
00693     return leaf_match(name, s);
00694 }
00695 
00696 BaseType *
00697 DDS::leaf_match(const string &n, BaseType::btp_stack *s)
00698 {
00699     DBG(cerr << "DDS::leaf_match: Looking for " << n << endl);
00700 
00701     for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
00702         BaseType *btp = *i;
00703         DBG(cerr << "DDS::leaf_match: Looking for " << n << " in: " << btp->name() << endl);
00704         // Look for the name in the dataset's top-level
00705         if (btp->name() == n) {
00706             DBG(cerr << "Found " << n << " in: " << btp->name() << endl);
00707             return btp;
00708         }
00709 
00710         if (btp->is_constructor_type()) {
00711             BaseType *found = btp->var(n, false, s);
00712             if (found) {
00713                 DBG(cerr << "Found " << n << " in: " << btp->name() << endl);
00714                 return found;
00715             }
00716         }
00717 #if STRUCTURE_ARRAY_SYNTAX_OLD
00718         if (btp->is_vector_type() && btp->var()->is_constructor_type()) {
00719             s->push(btp);
00720             BaseType *found = btp->var()->var(n, false, s);
00721             if (found) {
00722                 DBG(cerr << "Found " << n << " in: " << btp->var()->name() << endl);
00723                 return found;
00724             }
00725         }
00726 #endif
00727     }
00728 
00729     return 0;   // It is not here.
00730 }
00731 
00732 BaseType *
00733 DDS::exact_match(const string &name, BaseType::btp_stack *s)
00734 {
00735     for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
00736         BaseType *btp = *i;
00737         DBG2(cerr << "Looking for " << name << " in: " << btp << endl);
00738         // Look for the name in the current ctor type or the top level
00739         if (btp->name() == name) {
00740             DBG2(cerr << "Found " << name << " in: " << btp << endl);
00741             return btp;
00742         }
00743     }
00744 
00745     string::size_type dot_pos = name.find(".");
00746     if (dot_pos != string::npos) {
00747         string aggregate = name.substr(0, dot_pos);
00748         string field = name.substr(dot_pos + 1);
00749 
00750         BaseType *agg_ptr = var(aggregate, s);
00751         if (agg_ptr) {
00752             DBG2(cerr << "Descending into " << agg_ptr->name() << endl);
00753             return agg_ptr->var(field, true, s);
00754         }
00755         else
00756             return 0;  // qualified names must be *fully* qualified
00757     }
00758 
00759     return 0;   // It is not here.
00760 }
00761 
00762 
00765 DDS::Vars_iter
00766 DDS::var_begin()
00767 {
00768     return vars.begin();
00769 }
00770 
00771 DDS::Vars_riter
00772 DDS::var_rbegin()
00773 {
00774     return vars.rbegin();
00775 }
00776 
00777 DDS::Vars_iter
00778 DDS::var_end()
00779 {
00780     return vars.end() ;
00781 }
00782 
00783 DDS::Vars_riter
00784 DDS::var_rend()
00785 {
00786     return vars.rend() ;
00787 }
00788 
00792 DDS::Vars_iter
00793 DDS::get_vars_iter(int i)
00794 {
00795     return vars.begin() + i;
00796 }
00797 
00801 BaseType *
00802 DDS::get_var_index(int i)
00803 {
00804     return *(vars.begin() + i);
00805 }
00806 
00808 int
00809 DDS::num_var()
00810 {
00811     return vars.size();
00812 }
00813 
00814 void
00815 DDS::timeout_on()
00816 {
00817 #ifndef WIN32
00818     alarm(d_timeout);
00819 #endif
00820 }
00821 
00822 void
00823 DDS::timeout_off()
00824 {
00825 #ifndef WIN32
00826     d_timeout = alarm(0);
00827 #endif
00828 }
00829 
00830 void
00831 DDS::set_timeout(int t)
00832 {
00833     //  Has no effect under win32
00834     d_timeout = t;
00835 }
00836 
00837 int
00838 DDS::get_timeout()
00839 {
00840     //  Has to effect under win32
00841     return d_timeout;
00842 }
00843 
00845 void
00846 DDS::tag_nested_sequences()
00847 {
00848     for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
00849         if ((*i)->type() == dods_sequence_c)
00850             dynamic_cast<Sequence&>(**i).set_leaf_sequence();
00851         else if ((*i)->type() == dods_structure_c)
00852             dynamic_cast<Structure&>(**i).set_leaf_sequence();
00853     }
00854 }
00855 
00857 void
00858 DDS::parse(string fname)
00859 {
00860     FILE *in = fopen(fname.c_str(), "r");
00861 
00862     if (!in) {
00863         throw Error(cannot_read_file, "Could not open: " + fname);
00864     }
00865 
00866     try {
00867         parse(in);
00868         fclose(in);
00869     }
00870     catch (Error &e) {
00871         fclose(in);
00872         throw e;
00873     }
00874 }
00875 
00876 
00878 void
00879 DDS::parse(int fd)
00880 {
00881 #ifdef WIN32
00882     FILE *in = fdopen(_dup(fd), "r");
00883 #else
00884     FILE *in = fdopen(dup(fd), "r");
00885 #endif
00886 
00887     if (!in) {
00888         throw InternalErr(__FILE__, __LINE__, "Could not access file.");
00889     }
00890 
00891     try {
00892         parse(in);
00893         fclose(in);
00894     }
00895     catch (Error &e) {
00896         fclose(in);
00897         throw e;
00898     }
00899 }
00900 
00907 void
00908 DDS::parse(FILE *in)
00909 {
00910     if (!in) {
00911         throw InternalErr(__FILE__, __LINE__, "Null input stream.");
00912     }
00913 
00914     void *buffer = dds_buffer(in);
00915     dds_switch_to_buffer(buffer);
00916 
00917     parser_arg arg(this);
00918 
00919     bool status = ddsparse((void *) & arg) == 0;
00920 
00921     dds_delete_buffer(buffer);
00922 
00923     DBG2(cout << "Status from parser: " << status << endl);
00924 
00925     //  STATUS is the result of the parser function; if a recoverable error
00926     //  was found it will be true but arg.status() will be false.
00927     if (!status || !arg.status()) {// Check parse result
00928         if (arg.error())
00929             throw *arg.error();
00930     }
00931 }
00932 
00933 #if FILE_METHODS
00934 
00935 void
00936 DDS::print(FILE *out)
00937 {
00938     fprintf(out, "Dataset {\n") ;
00939 
00940     for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
00941         (*i)->print_decl(out) ;
00942     }
00943 
00944     fprintf(out, "} %s;\n", id2www(name).c_str()) ;
00945 
00946     return ;
00947 }
00948 #endif
00949 
00951 void
00952 DDS::print(ostream &out)
00953 {
00954     out << "Dataset {\n" ;
00955 
00956     for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
00957         (*i)->print_decl(out) ;
00958     }
00959 
00960     out << "} " << id2www(name) << ";\n" ;
00961 
00962     return ;
00963 }
00964 
00965 #if FILE_METHODS
00966 
00976 void
00977 DDS::print_constrained(FILE *out)
00978 {
00979     fprintf(out, "Dataset {\n") ;
00980 
00981     for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
00982         // for each variable, indent with four spaces, print a trailing
00983         // semicolon, do not print debugging information, print only
00984         // variables in the current projection.
00985         (*i)->print_decl(out, "    ", true, false, true) ;
00986     }
00987 
00988     fprintf(out, "} %s;\n", id2www(name).c_str()) ;
00989 
00990     return;
00991 }
00992 #endif
00993 
01004 void
01005 DDS::print_constrained(ostream &out)
01006 {
01007     out << "Dataset {\n" ;
01008 
01009     for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
01010         // for each variable, indent with four spaces, print a trailing
01011         // semicolon, do not print debugging information, print only
01012         // variables in the current projection.
01013         (*i)->print_decl(out, "    ", true, false, true) ;
01014     }
01015 
01016     out << "} " << id2www(name) << ";\n" ;
01017 
01018     return;
01019 }
01020 
01021 #if FILE_METHODS
01022 class VariablePrintXML : public unary_function<BaseType *, void>
01023 {
01024     FILE *d_out;
01025     bool d_constrained;
01026 public:
01027     VariablePrintXML(FILE *out, bool constrained)
01028             : d_out(out), d_constrained(constrained)
01029     {}
01030     void operator()(BaseType *bt)
01031     {
01032         bt->print_xml(d_out, "    ", d_constrained);
01033     }
01034 };
01035 
01046 void
01047 DDS::print_xml(FILE *out, bool constrained, const string &blob)
01048 {
01049     fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
01050 
01051     fprintf(out, "<Dataset name=\"%s\"\n", id2xml(name).c_str());
01052 
01053     fprintf(out, "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
01054 
01055     fprintf(out,"method=\"FILE*\"\n");
01056     fprintf(out, "dap_major=\"%d\"\n", get_dap_major());
01057     fprintf(out, "dap_minor=\"%d\"\n", get_dap_minor());
01058 
01059     // Are we responding to a 3.2 or 2.0 client? We will have to improve on
01060     // this at some point... jhrg
01061     if (get_dap_major() == 3 && get_dap_minor() == 2) {
01062     fprintf(out, "xmlns=\"%s\"\n", c_dap32_namespace.c_str());
01063 
01064     fprintf(out, "xsi:schemaLocation=\"%s  %s\">\n\n",
01065             c_dap32_namespace.c_str(), c_default_dap32_schema_location.c_str());
01066     }
01067     else {
01068         fprintf(out, "xmlns=\"%s\"\n", c_dap20_namespace.c_str());
01069         fprintf(out, "xsi:schemaLocation=\"%s  %s\">\n\n",
01070                 c_dap20_namespace.c_str(), c_default_dap20_schema_location.c_str());
01071     }
01072 
01073 
01074     d_attr.print_xml(out, "    ", constrained);
01075 
01076     fprintf(out, "\n");
01077 
01078     for_each(var_begin(), var_end(), VariablePrintXML(out, constrained));
01079 
01080     fprintf(out, "\n");
01081 
01082     // Only print this for the 2.0, 3.0 and 3.1 versions - which are essentially
01083     // the same. jhrg
01084     if (get_dap_major() == 2 && get_dap_minor() == 0) {
01085         fprintf(out, "    <dataBLOB href=\"\"/>\n");
01086     }
01087     else if (!blob.empty()
01088              && (get_dap_major() == 3 && get_dap_minor() >= 2)
01089              || get_dap_major() >= 4) {
01090         fprintf(out, "    <blob href=\"cid:%s\"/>\n", blob.c_str());
01091     }
01092 
01093 
01094     fprintf(out, "</Dataset>\n");
01095 }
01096 #endif
01097 
01098 class VariablePrintXMLStrm : public unary_function<BaseType *, void>
01099 {
01100     ostream &d_out;
01101     bool d_constrained;
01102 public:
01103     VariablePrintXMLStrm(ostream &out, bool constrained)
01104             : d_out(out), d_constrained(constrained)
01105     {}
01106     void operator()(BaseType *bt)
01107     {
01108         bt->print_xml(d_out, "    ", d_constrained);
01109     }
01110 };
01111 
01122 void
01123 DDS::print_xml(ostream &out, bool constrained, const string &blob)
01124 {
01125     out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ;
01126 
01127     out << "<Dataset name=\"" << id2xml(name) << "\"\n" ;
01128 
01129     out << "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" ;
01130 
01131     // Are we responding to a 3.2 or 2.0 client? We will have to improve on
01132     // this at some point... jhrg
01133     if (get_dap_major() == 3 && get_dap_minor() == 2) {
01134         out << "xsi:schemaLocation=\"" << c_dap32_namespace
01135             << "  " << c_default_dap32_schema_location << "\"\n" ;
01136 
01137         out << "xmlns:grddl=\"http://www.w3.org/2003/g/data-view#\"\n";
01138         out << "grddl:transformation=\"" << grddl_transformation_dap32 <<"\"\n";
01139 
01140         out << "xmlns=\"" << c_dap32_namespace << "\"\n" ;
01141         out << "xmlns:dap=\"" << c_dap32_namespace << "\"\n" ;
01142 
01143         out << "dapVersion=\"" << get_dap_major() << "."
01144             << get_dap_minor() << "\"";
01145 
01146         if (!get_request_xml_base().empty()) {
01147             out << "\n";
01148             out << "xmlns:xml=\"" << c_xml_namespace << "\"\n";
01149             out << "xml:base=\"" << get_request_xml_base() << "\"";
01150         }
01151 
01152         // Close the Dataset element
01153         out << ">\n";
01154     }
01155     else {
01156         out << "xmlns=\"" << c_dap20_namespace << "\"\n" ;
01157         out << "xsi:schemaLocation=\"" << c_dap20_namespace
01158             << "  " << c_default_dap20_schema_location << "\">\n\n" ;
01159     }
01160 
01161     d_attr.print_xml(out, "    ", constrained);
01162 
01163     out << "\n" ;
01164 
01165     for_each(var_begin(), var_end(), VariablePrintXMLStrm(out, constrained));
01166 
01167     out << "\n" ;
01168 
01169     // Only print this for the 2.0, 3.0 and 3.1 versions - which are essentially
01170     // the same.
01171     // For DAP 3.2 and greater, use the new syntax and value. The 'blob' is
01172     // actually the CID of the MIME part that holds the data.
01173     if (get_dap_major() == 2 && get_dap_minor() == 0) {
01174         out << "    <dataBLOB href=\"\"/>\n" ;
01175     }
01176     else if (!blob.empty()
01177              && (get_dap_major() == 3 && get_dap_minor() >= 2)
01178              || get_dap_major() >= 4) {
01179         out << "    <blob href=\"cid:" << blob << "\"/>\n";
01180     }
01181 
01182     out << "</Dataset>\n" ;
01183 }
01184 
01185 // Used by DDS::send() when returning data from a function call.
01200 bool
01201 DDS::check_semantics(bool all)
01202 {
01203     // The dataset must have a name
01204     if (name == "") {
01205         cerr << "A dataset must have a name" << endl;
01206         return false;
01207     }
01208 
01209     string msg;
01210     if (!unique_names(vars, name, "Dataset", msg))
01211         return false;
01212 
01213     if (all)
01214         for (Vars_iter i = vars.begin(); i != vars.end(); i++)
01215             if (!(*i)->check_semantics(msg, true))
01216                 return false;
01217 
01218     return true;
01219 }
01220 
01246 bool
01247 DDS::mark(const string &n, bool state)
01248 {
01249     BaseType::btp_stack *s = new BaseType::btp_stack;
01250 
01251     DBG2(cerr << "DDS::mark: Looking for " << n << endl);
01252 
01253     BaseType *variable = var(n, s);
01254     if (!variable) {
01255         DBG2(cerr << "Could not find variable " << n << endl);
01256         delete s; s = 0;
01257         return false;
01258     }
01259     variable->set_send_p(state);
01260 
01261     DBG2(cerr << "DDS::mark: Set variable " << variable->name()
01262             << " (a " << variable->type_name() << ")" << endl);
01263 
01264     // Now check the btp_stack and run BaseType::set_send_p for every
01265     // BaseType pointer on the stack. Using BaseType::set_send_p() will
01266     // set the property for a Constructor but not its contained variables
01267     // which preserves the semantics of projecting just one field.
01268     while (!s->empty()) {
01269         s->top()->BaseType::set_send_p(state);
01270 
01271         DBG2(cerr << "DDS::mark: Set variable " << s->top()->name()
01272                 << " (a " << s->top()->type_name() << ")" << endl);
01273         string parent_name = (s->top()->get_parent()) ? s->top()->get_parent()->name(): "none";
01274         string parent_type = (s->top()->get_parent()) ? s->top()->get_parent()->type_name(): "none";
01275         DBG2(cerr << "DDS::mark: Parent variable " << parent_name << " (a " << parent_type << ")" << endl);
01276 
01277         s->pop();
01278     }
01279 
01280     delete s ; s = 0;
01281 
01282     return true;
01283 }
01284 
01290 void
01291 DDS::mark_all(bool state)
01292 {
01293     for (Vars_iter i = vars.begin(); i != vars.end(); i++)
01294         (*i)->set_send_p(state);
01295 }
01296 
01304 void
01305 DDS::dump(ostream &strm) const
01306 {
01307     strm << DapIndent::LMarg << "DDS::dump - ("
01308     << (void *)this << ")" << endl ;
01309     DapIndent::Indent() ;
01310     strm << DapIndent::LMarg << "name: " << name << endl ;
01311     strm << DapIndent::LMarg << "filename: " << d_filename << endl ;
01312     strm << DapIndent::LMarg << "protocol major: " << d_dap_major << endl;
01313     strm << DapIndent::LMarg << "protocol minor: " << d_dap_minor << endl;
01314     strm << DapIndent::LMarg << "factory: " << (void *)d_factory << endl ;
01315 
01316     strm << DapIndent::LMarg << "global attributes:" << endl ;
01317     DapIndent::Indent() ;
01318     d_attr.dump(strm) ;
01319     DapIndent::UnIndent() ;
01320 
01321     if (vars.size()) {
01322         strm << DapIndent::LMarg << "vars:" << endl ;
01323         DapIndent::Indent() ;
01324         Vars_citer i = vars.begin() ;
01325         Vars_citer ie = vars.end() ;
01326         for (; i != ie; i++) {
01327             (*i)->dump(strm) ;
01328         }
01329         DapIndent::UnIndent() ;
01330     }
01331     else {
01332         strm << DapIndent::LMarg << "vars: none" << endl ;
01333     }
01334 
01335     DapIndent::UnIndent() ;
01336 }
01337 
01338 } // namespace libdap

Generated on Wed Jun 2 11:49:18 2010 for libdap++ by  doxygen 1.4.7