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 21975 2010-01-12 17:14:54Z 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 
00197 BaseType *
00198 DDS::find_hdf4_dimension_attribute_home(AttrTable::entry *source)
00199 {
00200     BaseType *btp;
00201     string::size_type i = source->name.find("_dim_");
00202     if (i != string::npos && (btp = var(source->name.substr(0, i)))) {
00203         if (btp->is_vector_type()) {
00204             return btp;
00205         }
00206         else if (btp->type() == dods_grid_c) {
00207             // For a Grid, the hdf4 handler uses _dim_n for the n-th Map
00208             // i+5 points to the character holding 'n'
00209             int n = atoi(source->name.substr(i + 5).c_str());
00210             DBG(cerr << "Found a Grid (" << btp->name() << ") and "
00211                 << source->name.substr(i) << ", extracted n: " << n << endl);
00212             return *(dynamic_cast<Grid&>(*btp).map_begin() + n);
00213         }
00214     }
00215 
00216     return 0;
00217 }
00218 
00224 AttrTable *
00225 DDS::find_matching_container(AttrTable::entry *source, BaseType **dest_variable)
00226 {
00227     // The attribute entry 'source' must be a container
00228     if (source->type != Attr_container)
00229         throw InternalErr(__FILE__, __LINE__, "DDS::find_matching_container");
00230 
00231     // Use the name of the attribute container 'source' to figure out where
00232     // to put its contents.
00233     BaseType *btp;
00234     if ((btp = var(source->name))) {
00235         // ... matches a variable name? Use var's table
00236         *dest_variable = btp;
00237         return &btp->get_attr_table();
00238     }
00239     else if ((btp = find_hdf4_dimension_attribute_home(source))) {
00240         // ... hdf4 dimension attribute? Make a sub table and use that.
00241         // btp can only be an Array or a Grid Map (which is an array)
00242         if (btp->get_parent() && btp->get_parent()->type() == dods_grid_c) {
00243             DBG(cerr << "Found a Grid, assigning to the map" << endl);
00244             *dest_variable = btp;
00245             return &btp->get_attr_table();
00246         }
00247         else { // must ba a plain Array
00248             string::size_type i = source->name.find("_dim_");
00249             string ext = source->name.substr(i + 1);
00250             *dest_variable = btp;
00251             return btp->get_attr_table().append_container(ext);
00252         }
00253     }
00254     else {
00255         // ... otherwise assume it's a global attribute.
00256         AttrTable *at = d_attr.find_container(source->name);
00257         if (!at) {
00258             at = new AttrTable();       // Make a new global table if needed
00259             d_attr.append_container(at, source->name);
00260         }
00261 
00262         *dest_variable = 0;
00263         return at;
00264     }
00265 }
00266 
00288 void
00289 DDS::transfer_attributes(DAS *das)
00290 {
00291     // If there is a container set in the DDS then get the container from
00292     // the DAS. If they are not the same container, then throw an exception
00293     // (should be working on the same container). If the container does not
00294     // exist in the DAS, then throw an exception
00295     if( d_container )
00296     {
00297         if( das->container_name() != d_container_name )
00298         {
00299             string err = (string)"Error transferring attributes: "
00300                          + "working on container in dds, but not das" ;
00301             throw InternalErr(__FILE__, __LINE__, err ) ;
00302         }
00303     }
00304     AttrTable *top_level = das->get_top_level_attributes() ;
00305 
00306     // foreach container at the outer level
00307     AttrTable::Attr_iter das_i = top_level->attr_begin();
00308     AttrTable::Attr_iter das_e = top_level->attr_end();
00309     while (das_i != das_e) {
00310         DBG(cerr << "Working on the '" << (*das_i)->name << "' container."
00311             << endl);
00312 
00313         AttrTable *source = (*das_i)->attributes;
00314         // Variable that holds 'dest'; null for a global attribute.
00315         BaseType *dest_variable = 0;
00316         AttrTable *dest = find_matching_container(*das_i, &dest_variable);
00317 
00318         // foreach source attribute in the das_i container
00319         AttrTable::Attr_iter source_p = source->attr_begin();
00320         while (source_p != source->attr_end()) {
00321             DBG(cerr << "Working on the '" << (*source_p)->name << "' attribute"
00322                 << endl);
00323 
00324             // If this is an attribute container, we must have a container
00325             // (this one) within a container (the 'source'). Look and see if
00326             // the variable is a Constructor. If so, pass that container into
00327             // Constructor::transfer_attributes()
00328             if ((*source_p)->type == Attr_container) {
00329                 if (dest_variable && dest_variable->is_constructor_type()) {
00330                     dynamic_cast<Constructor&>(*dest_variable).transfer_attributes(*source_p);
00331                 }
00332                 else {
00333                     dest->append_container(new AttrTable(*(*source_p)->attributes),
00334                                            (*source_p)->name);
00335                 }
00336             }
00337             else {
00338                 dest->append_attr(source->get_name(source_p),
00339                                   source->get_type(source_p),
00340                                   source->get_attr_vector(source_p));
00341             }
00342 
00343             ++source_p;
00344         }
00345 
00346         ++das_i;
00347     }
00348 }
00349 
00357 
00359 string
00360 DDS::get_dataset_name() const
00361 {
00362     return name;
00363 }
00364 
00366 void
00367 DDS::set_dataset_name(const string &n)
00368 {
00369     name = n;
00370 }
00371 
00373 
00375 AttrTable &
00376 DDS::get_attr_table()
00377 {
00378     return d_attr;
00379 }
00380 
00390 string
00391 DDS::filename()
00392 {
00393     return d_filename;
00394 }
00395 
00397 void
00398 DDS::filename(const string &fn)
00399 {
00400     d_filename = fn;
00401 }
00403 
00409 void
00410 DDS::set_dap_version(const string &version_string)
00411 {
00412     istringstream iss(version_string);
00413 
00414     int major = -1, minor = -1;
00415     char dot;
00416     iss >> major;
00417     iss >> dot;
00418     iss >> minor;
00419 
00420     DBG(cerr << "Major: " << major << ", dot: " << dot <<", Minor: " << minor << endl);
00421 
00422     if (major == -1 || minor == -1)
00423         throw Error("Could not parse the client dap (XDAP-Accept header) value");
00424 
00425     set_dap_major(major);
00426     set_dap_minor(minor);
00427 }
00428 
00438 string
00439 DDS::container_name()
00440 {
00441     return d_container_name;
00442 }
00443 
00446 void
00447 DDS::container_name(const string &cn)
00448 {
00449     // we want to search the DDS for the top level structure with the given
00450     // name. Set the container to null so that we don't search some previous
00451     // container.
00452     d_container = 0 ;
00453     if( !cn.empty() )
00454     {
00455         d_container = dynamic_cast<Structure *>( var( cn ) ) ;
00456         if( !d_container )
00457         {
00458             // create a structure for this container. Calling add_var
00459             // while_container is null will add the new structure to DDS and
00460             // not some sub structure. Adding the new structure makes a copy
00461             // of it.  So after adding it, go get it and set d_container.
00462             Structure *s = new Structure( cn ) ;
00463             add_var( s ) ;
00464             delete s ;
00465             s = 0 ;
00466             d_container = dynamic_cast<Structure *>( var( cn ) ) ;
00467         }
00468     }
00469     d_container_name = cn;
00470 
00471 }
00472 
00474 Structure *
00475 DDS::container()
00476 {
00477     return d_container ;
00478 }
00479 
00481 
00487 void
00488 DDS::add_var(BaseType *bt)
00489 {
00490     if (!bt)
00491         throw InternalErr(__FILE__, __LINE__,
00492                           "Trying to add a BaseType object with a NULL pointer.");
00493 
00494     DBG2(cerr << "In DDS::add_var(), bt's address is: " << bt << endl);
00495 
00496     BaseType *btp = bt->ptr_duplicate();
00497     DBG2(cerr << "In DDS::add_var(), btp's address is: " << btp << endl);
00498     if( d_container )
00499     {
00500         // Mem leak fix [mjohnson nov 2009]
00501         // Structure::add_var() creates ANOTHER copy.
00502         d_container->add_var( bt ) ;
00503         // So we need to delete btp or else it leaks
00504         delete btp; btp = 0;
00505     }
00506     else
00507     {
00508         vars.push_back(btp);
00509     }
00510 }
00511 
00518 void
00519 DDS::del_var(const string &n)
00520 {
00521     if( d_container )
00522     {
00523         d_container->del_var( n ) ;
00524         return ;
00525     }
00526 
00527     for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
00528         if ((*i)->name() == n) {
00529             BaseType *bt = *i ;
00530             vars.erase(i) ;
00531             delete bt ; bt = 0;
00532             return;
00533         }
00534     }
00535 }
00536 
00541 void
00542 DDS::del_var(Vars_iter i)
00543 {
00544     if (i != vars.end()) {
00545         BaseType *bt = *i ;
00546         vars.erase(i) ;
00547         delete bt ; bt = 0;
00548     }
00549 }
00550 
00557 void
00558 DDS::del_var(Vars_iter i1, Vars_iter i2)
00559 {
00560     for (Vars_iter i_tmp = i1; i_tmp != i2; i_tmp++) {
00561         BaseType *bt = *i_tmp ;
00562         delete bt ; bt = 0;
00563     }
00564     vars.erase(i1, i2) ;
00565 }
00566 
00574 BaseType *
00575 DDS::var(const string &n, BaseType::btp_stack &s)
00576 {
00577     return var(n, &s);
00578 }
00598 BaseType *
00599 DDS::var(const string &n, BaseType::btp_stack *s)
00600 {
00601     string name = www2id(n);
00602     if( d_container )
00603         return d_container->var( name, false, s ) ;
00604 
00605     BaseType *v = exact_match(name, s);
00606     if (v)
00607         return v;
00608 
00609     return leaf_match(name, s);
00610 }
00611 
00612 BaseType *
00613 DDS::leaf_match(const string &n, BaseType::btp_stack *s)
00614 {
00615     DBG(cerr << "DDS::leaf_match: Looking for " << n << endl);
00616 
00617     for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
00618         BaseType *btp = *i;
00619         DBG(cerr << "DDS::leaf_match: Looking for " << n << " in: " << btp->name() << endl);
00620         // Look for the name in the dataset's top-level
00621         if (btp->name() == n) {
00622             DBG(cerr << "Found " << n << " in: " << btp->name() << endl);
00623             return btp;
00624         }
00625 
00626         if (btp->is_constructor_type()) {
00627             BaseType *found = btp->var(n, false, s);
00628             if (found) {
00629                 DBG(cerr << "Found " << n << " in: " << btp->name() << endl);
00630                 return found;
00631             }
00632         }
00633 #if STRUCTURE_ARRAY_SYNTAX_OLD
00634         if (btp->is_vector_type() && btp->var()->is_constructor_type()) {
00635             s->push(btp);
00636             BaseType *found = btp->var()->var(n, false, s);
00637             if (found) {
00638                 DBG(cerr << "Found " << n << " in: " << btp->var()->name() << endl);
00639                 return found;
00640             }
00641         }
00642 #endif
00643     }
00644 
00645     return 0;   // It is not here.
00646 }
00647 
00648 BaseType *
00649 DDS::exact_match(const string &name, BaseType::btp_stack *s)
00650 {
00651     for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
00652         BaseType *btp = *i;
00653         DBG2(cerr << "Looking for " << name << " in: " << btp << endl);
00654         // Look for the name in the current ctor type or the top level
00655         if (btp->name() == name) {
00656             DBG2(cerr << "Found " << name << " in: " << btp << endl);
00657             return btp;
00658         }
00659     }
00660 
00661     string::size_type dot_pos = name.find(".");
00662     if (dot_pos != string::npos) {
00663         string aggregate = name.substr(0, dot_pos);
00664         string field = name.substr(dot_pos + 1);
00665 
00666         BaseType *agg_ptr = var(aggregate, s);
00667         if (agg_ptr) {
00668             DBG2(cerr << "Descending into " << agg_ptr->name() << endl);
00669             return agg_ptr->var(field, true, s);
00670         }
00671         else
00672             return 0;  // qualified names must be *fully* qualified
00673     }
00674 
00675     return 0;   // It is not here.
00676 }
00677 
00678 
00681 DDS::Vars_iter
00682 DDS::var_begin()
00683 {
00684     return vars.begin();
00685 }
00686 
00687 DDS::Vars_riter
00688 DDS::var_rbegin()
00689 {
00690     return vars.rbegin();
00691 }
00692 
00693 DDS::Vars_iter
00694 DDS::var_end()
00695 {
00696     return vars.end() ;
00697 }
00698 
00699 DDS::Vars_riter
00700 DDS::var_rend()
00701 {
00702     return vars.rend() ;
00703 }
00704 
00708 DDS::Vars_iter
00709 DDS::get_vars_iter(int i)
00710 {
00711     return vars.begin() + i;
00712 }
00713 
00717 BaseType *
00718 DDS::get_var_index(int i)
00719 {
00720     return *(vars.begin() + i);
00721 }
00722 
00724 int
00725 DDS::num_var()
00726 {
00727     return vars.size();
00728 }
00729 
00730 void
00731 DDS::timeout_on()
00732 {
00733 #ifndef WIN32
00734     alarm(d_timeout);
00735 #endif
00736 }
00737 
00738 void
00739 DDS::timeout_off()
00740 {
00741 #ifndef WIN32
00742     d_timeout = alarm(0);
00743 #endif
00744 }
00745 
00746 void
00747 DDS::set_timeout(int t)
00748 {
00749     //  Has no effect under win32
00750     d_timeout = t;
00751 }
00752 
00753 int
00754 DDS::get_timeout()
00755 {
00756     //  Has to effect under win32
00757     return d_timeout;
00758 }
00759 
00761 void
00762 DDS::tag_nested_sequences()
00763 {
00764     for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
00765         if ((*i)->type() == dods_sequence_c)
00766             dynamic_cast<Sequence&>(**i).set_leaf_sequence();
00767         else if ((*i)->type() == dods_structure_c)
00768             dynamic_cast<Structure&>(**i).set_leaf_sequence();
00769     }
00770 }
00771 
00773 void
00774 DDS::parse(string fname)
00775 {
00776     FILE *in = fopen(fname.c_str(), "r");
00777 
00778     if (!in) {
00779         throw Error(cannot_read_file, "Could not open: " + fname);
00780     }
00781 
00782     try {
00783         parse(in);
00784         fclose(in);
00785     }
00786     catch (Error &e) {
00787         fclose(in);
00788         throw e;
00789     }
00790 }
00791 
00792 
00794 void
00795 DDS::parse(int fd)
00796 {
00797 #ifdef WIN32
00798     FILE *in = fdopen(_dup(fd), "r");
00799 #else
00800     FILE *in = fdopen(dup(fd), "r");
00801 #endif
00802 
00803     if (!in) {
00804         throw InternalErr(__FILE__, __LINE__, "Could not access file.");
00805     }
00806 
00807     try {
00808         parse(in);
00809         fclose(in);
00810     }
00811     catch (Error &e) {
00812         fclose(in);
00813         throw e;
00814     }
00815 }
00816 
00823 void
00824 DDS::parse(FILE *in)
00825 {
00826     if (!in) {
00827         throw InternalErr(__FILE__, __LINE__, "Null input stream.");
00828     }
00829 
00830     void *buffer = dds_buffer(in);
00831     dds_switch_to_buffer(buffer);
00832 
00833     parser_arg arg(this);
00834 
00835     bool status = ddsparse((void *) & arg) == 0;
00836 
00837     dds_delete_buffer(buffer);
00838 
00839     DBG2(cout << "Status from parser: " << status << endl);
00840 
00841     //  STATUS is the result of the parser function; if a recoverable error
00842     //  was found it will be true but arg.status() will be false.
00843     if (!status || !arg.status()) {// Check parse result
00844         if (arg.error())
00845             throw *arg.error();
00846     }
00847 }
00848 
00849 #if FILE_METHODS
00850 
00851 void
00852 DDS::print(FILE *out)
00853 {
00854     fprintf(out, "Dataset {\n") ;
00855 
00856     for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
00857         (*i)->print_decl(out) ;
00858     }
00859 
00860     fprintf(out, "} %s;\n", id2www(name).c_str()) ;
00861 
00862     return ;
00863 }
00864 #endif
00865 
00867 void
00868 DDS::print(ostream &out)
00869 {
00870     out << "Dataset {\n" ;
00871 
00872     for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
00873         (*i)->print_decl(out) ;
00874     }
00875 
00876     out << "} " << id2www(name) << ";\n" ;
00877 
00878     return ;
00879 }
00880 
00881 #if FILE_METHODS
00882 
00892 void
00893 DDS::print_constrained(FILE *out)
00894 {
00895     fprintf(out, "Dataset {\n") ;
00896 
00897     for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
00898         // for each variable, indent with four spaces, print a trailing
00899         // semicolon, do not print debugging information, print only
00900         // variables in the current projection.
00901         (*i)->print_decl(out, "    ", true, false, true) ;
00902     }
00903 
00904     fprintf(out, "} %s;\n", id2www(name).c_str()) ;
00905 
00906     return;
00907 }
00908 #endif
00909 
00920 void
00921 DDS::print_constrained(ostream &out)
00922 {
00923     out << "Dataset {\n" ;
00924 
00925     for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
00926         // for each variable, indent with four spaces, print a trailing
00927         // semicolon, do not print debugging information, print only
00928         // variables in the current projection.
00929         (*i)->print_decl(out, "    ", true, false, true) ;
00930     }
00931 
00932     out << "} " << id2www(name) << ";\n" ;
00933 
00934     return;
00935 }
00936 
00937 #if FILE_METHODS
00938 class VariablePrintXML : public unary_function<BaseType *, void>
00939 {
00940     FILE *d_out;
00941     bool d_constrained;
00942 public:
00943     VariablePrintXML(FILE *out, bool constrained)
00944             : d_out(out), d_constrained(constrained)
00945     {}
00946     void operator()(BaseType *bt)
00947     {
00948         bt->print_xml(d_out, "    ", d_constrained);
00949     }
00950 };
00951 
00962 void
00963 DDS::print_xml(FILE *out, bool constrained, const string &blob)
00964 {
00965     fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
00966 
00967     fprintf(out, "<Dataset name=\"%s\"\n", id2xml(name).c_str());
00968 
00969     fprintf(out, "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
00970 
00971     fprintf(out,"method=\"FILE*\"\n");
00972     fprintf(out, "dap_major=\"%d\"\n", get_dap_major());
00973     fprintf(out, "dap_minor=\"%d\"\n", get_dap_minor());
00974 
00975     // Are we responding to a 3.2 or 2.0 client? We will have to improve on
00976     // this at some point... jhrg
00977     if (get_dap_major() == 3 && get_dap_minor() == 2) {
00978     fprintf(out, "xmlns=\"%s\"\n", c_dap32_namespace.c_str());
00979 
00980     fprintf(out, "xsi:schemaLocation=\"%s  %s\">\n\n",
00981             c_dap32_namespace.c_str(), c_default_dap32_schema_location.c_str());
00982     }
00983     else {
00984         fprintf(out, "xmlns=\"%s\"\n", c_dap20_namespace.c_str());
00985         fprintf(out, "xsi:schemaLocation=\"%s  %s\">\n\n",
00986                 c_dap20_namespace.c_str(), c_default_dap20_schema_location.c_str());
00987     }
00988 
00989 
00990     d_attr.print_xml(out, "    ", constrained);
00991 
00992     fprintf(out, "\n");
00993 
00994     for_each(var_begin(), var_end(), VariablePrintXML(out, constrained));
00995 
00996     fprintf(out, "\n");
00997 
00998     // Only print this for the 2.0, 3.0 and 3.1 versions - which are essentially
00999     // the same. jhrg
01000     if (get_dap_major() == 2 && get_dap_minor() == 0) {
01001         fprintf(out, "    <dataBLOB href=\"\"/>\n");
01002     }
01003     else if (!blob.empty()
01004              && (get_dap_major() == 3 && get_dap_minor() >= 2)
01005              || get_dap_major() >= 4) {
01006         fprintf(out, "    <blob href=\"cid:%s\"/>\n", blob.c_str());
01007     }
01008 
01009 
01010     fprintf(out, "</Dataset>\n");
01011 }
01012 #endif
01013 
01014 class VariablePrintXMLStrm : public unary_function<BaseType *, void>
01015 {
01016     ostream &d_out;
01017     bool d_constrained;
01018 public:
01019     VariablePrintXMLStrm(ostream &out, bool constrained)
01020             : d_out(out), d_constrained(constrained)
01021     {}
01022     void operator()(BaseType *bt)
01023     {
01024         bt->print_xml(d_out, "    ", d_constrained);
01025     }
01026 };
01027 
01038 void
01039 DDS::print_xml(ostream &out, bool constrained, const string &blob)
01040 {
01041     out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ;
01042 
01043     out << "<Dataset name=\"" << id2xml(name) << "\"\n" ;
01044 
01045     out << "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" ;
01046 
01047     // Are we responding to a 3.2 or 2.0 client? We will have to improve on
01048     // this at some point... jhrg
01049     if (get_dap_major() == 3 && get_dap_minor() == 2) {
01050         out << "xsi:schemaLocation=\"" << c_dap32_namespace
01051             << "  " << c_default_dap32_schema_location << "\"\n" ;
01052 
01053         out << "xmlns:grddl=\"http://www.w3.org/2003/g/data-view#\"\n";
01054         out << "grddl:transformation=\"" << grddl_transformation_dap32 <<"\"\n";
01055 
01056         out << "xmlns=\"" << c_dap32_namespace << "\"\n" ;
01057         out << "xmlns:dap=\"" << c_dap32_namespace << "\"\n" ;
01058 
01059         out << "dapVersion=\"" << get_dap_major() << "."
01060             << get_dap_minor() << "\"";
01061 
01062         if (!get_request_xml_base().empty()) {
01063             out << "\n";
01064             out << "xmlns:xml=\"" << c_xml_namespace << "\"\n";
01065             out << "xml:base=\"" << get_request_xml_base() << "\"";
01066         }
01067 
01068         // Close the Dataset element
01069         out << ">\n";
01070     }
01071     else {
01072         out << "xmlns=\"" << c_dap20_namespace << "\"\n" ;
01073         out << "xsi:schemaLocation=\"" << c_dap20_namespace
01074             << "  " << c_default_dap20_schema_location << "\">\n\n" ;
01075     }
01076 
01077     d_attr.print_xml(out, "    ", constrained);
01078 
01079     out << "\n" ;
01080 
01081     for_each(var_begin(), var_end(), VariablePrintXMLStrm(out, constrained));
01082 
01083     out << "\n" ;
01084 
01085     // Only print this for the 2.0, 3.0 and 3.1 versions - which are essentially
01086     // the same.
01087     // For DAP 3.2 and greater, use the new syntax and value. The 'blob' is
01088     // actually the CID of the MIME part that holds the data.
01089     if (get_dap_major() == 2 && get_dap_minor() == 0) {
01090         out << "    <dataBLOB href=\"\"/>\n" ;
01091     }
01092     else if (!blob.empty()
01093              && (get_dap_major() == 3 && get_dap_minor() >= 2)
01094              || get_dap_major() >= 4) {
01095         out << "    <blob href=\"cid:" << blob << "\"/>\n";
01096     }
01097 
01098     out << "</Dataset>\n" ;
01099 }
01100 
01101 // Used by DDS::send() when returning data from a function call.
01116 bool
01117 DDS::check_semantics(bool all)
01118 {
01119     // The dataset must have a name
01120     if (name == "") {
01121         cerr << "A dataset must have a name" << endl;
01122         return false;
01123     }
01124 
01125     string msg;
01126     if (!unique_names(vars, name, "Dataset", msg))
01127         return false;
01128 
01129     if (all)
01130         for (Vars_iter i = vars.begin(); i != vars.end(); i++)
01131             if (!(*i)->check_semantics(msg, true))
01132                 return false;
01133 
01134     return true;
01135 }
01136 
01162 bool
01163 DDS::mark(const string &n, bool state)
01164 {
01165     BaseType::btp_stack *s = new BaseType::btp_stack;
01166 
01167     DBG2(cerr << "DDS::mark: Looking for " << n << endl);
01168 
01169     BaseType *variable = var(n, s);
01170     if (!variable) {
01171         DBG2(cerr << "Could not find variable " << n << endl);
01172         delete s; s = 0;
01173         return false;
01174     }
01175     variable->set_send_p(state);
01176 
01177     DBG2(cerr << "DDS::mark: Set variable " << variable->name()
01178             << " (a " << variable->type_name() << ")" << endl);
01179 
01180     // Now check the btp_stack and run BaseType::set_send_p for every
01181     // BaseType pointer on the stack. Using BaseType::set_send_p() will
01182     // set the property for a Constructor but not its contained variables
01183     // which preserves the semantics of projecting just one field.
01184     while (!s->empty()) {
01185         s->top()->BaseType::set_send_p(state);
01186 
01187         DBG2(cerr << "DDS::mark: Set variable " << s->top()->name()
01188                 << " (a " << s->top()->type_name() << ")" << endl);
01189         string parent_name = (s->top()->get_parent()) ? s->top()->get_parent()->name(): "none";
01190         string parent_type = (s->top()->get_parent()) ? s->top()->get_parent()->type_name(): "none";
01191         DBG2(cerr << "DDS::mark: Parent variable " << parent_name << " (a " << parent_type << ")" << endl);
01192 
01193         s->pop();
01194     }
01195 
01196     delete s ; s = 0;
01197 
01198     return true;
01199 }
01200 
01206 void
01207 DDS::mark_all(bool state)
01208 {
01209     for (Vars_iter i = vars.begin(); i != vars.end(); i++)
01210         (*i)->set_send_p(state);
01211 }
01212 
01220 void
01221 DDS::dump(ostream &strm) const
01222 {
01223     strm << DapIndent::LMarg << "DDS::dump - ("
01224     << (void *)this << ")" << endl ;
01225     DapIndent::Indent() ;
01226     strm << DapIndent::LMarg << "name: " << name << endl ;
01227     strm << DapIndent::LMarg << "filename: " << d_filename << endl ;
01228     strm << DapIndent::LMarg << "protocol major: " << d_dap_major << endl;
01229     strm << DapIndent::LMarg << "protocol minor: " << d_dap_minor << endl;
01230     strm << DapIndent::LMarg << "factory: " << (void *)d_factory << endl ;
01231 
01232     strm << DapIndent::LMarg << "global attributes:" << endl ;
01233     DapIndent::Indent() ;
01234     d_attr.dump(strm) ;
01235     DapIndent::UnIndent() ;
01236 
01237     if (vars.size()) {
01238         strm << DapIndent::LMarg << "vars:" << endl ;
01239         DapIndent::Indent() ;
01240         Vars_citer i = vars.begin() ;
01241         Vars_citer ie = vars.end() ;
01242         for (; i != ie; i++) {
01243             (*i)->dump(strm) ;
01244         }
01245         DapIndent::UnIndent() ;
01246     }
01247     else {
01248         strm << DapIndent::LMarg << "vars: none" << endl ;
01249     }
01250 
01251     DapIndent::UnIndent() ;
01252 }
01253 
01254 } // namespace libdap

Generated on Wed Feb 10 16:08:01 2010 for libdap++ by  doxygen 1.4.7