00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "config.h"
00035
00036 static char rcsid[] not_used =
00037 {"$Id: DDS.cc 23577 2010-09-14 22:20:18Z 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>
00049 #include <sys/wait.h>
00050 #endif
00051
00052 #include <iostream>
00053 #include <sstream>
00054 #include <algorithm>
00055 #include <functional>
00056
00057
00058
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);
00100 int ddsparse(void *arg);
00101
00102
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
00127 for (Vars_iter i = dds_tmp.var_begin(); i != dds_tmp.var_end(); i++) {
00128 add_var(*i);
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
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
00209
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
00229 if (source->type != Attr_container)
00230 throw InternalErr(__FILE__, __LINE__, "DDS::find_matching_container; expected 'source' to be a container.");
00231
00232
00233
00234 BaseType *btp;
00235 if ((btp = var(source->name))) {
00236
00237 *dest_variable = btp;
00238 return &btp->get_attr_table();
00239 }
00240 else if ((btp = find_hdf4_dimension_attribute_home(source))) {
00241
00242
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 {
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
00257 AttrTable *at = d_attr.find_container(source->name);
00258 if (!at) {
00259 at = new AttrTable();
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
00293
00294
00295
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
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
00317 BaseType *dest_variable = 0;
00318 AttrTable *dest = find_matching_container(*das_i, &dest_variable);
00319
00320
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
00327
00328
00329
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
00370
00371
00372
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
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
00389
00390
00391 AttrTable::Attr_iter at_cont_p = top_level->attr_begin();
00392 while (at_cont_p != top_level->attr_end()) {
00393
00394
00395
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
00400
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
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
00416
00417 dest = new AttrTable();
00418 d_attr.append_container(dest, at->get_name());
00419 }
00420
00421 cerr << "now copying its contents to the new container" << endl;
00422
00423
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
00534
00535
00536 d_container = 0 ;
00537 if( !cn.empty() )
00538 {
00539 d_container = dynamic_cast<Structure *>( var( cn ) ) ;
00540 if( !d_container )
00541 {
00542
00543
00544
00545
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
00585
00586 d_container->add_var( bt ) ;
00587
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
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;
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
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;
00757 }
00758
00759 return 0;
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
00834 d_timeout = t;
00835 }
00836
00837 int
00838 DDS::get_timeout()
00839 {
00840
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
00926
00927 if (!status || !arg.status()) {
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 #if 0
00939 ostringstream oss;
00940 print(oss);
00941
00942 fwrite(oss.str().c_str(), oss.str().length(), 1, out);
00943 #else
00944 fprintf(out, "Dataset {\n") ;
00945
00946 for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
00947 (*i)->print_decl(out) ;
00948 }
00949
00950 fprintf(out, "} %s;\n", id2www(name).c_str()) ;
00951
00952 return ;
00953 #endif
00954 }
00955 #endif
00956
00958 void
00959 DDS::print(ostream &out)
00960 {
00961 out << "Dataset {\n" ;
00962
00963 for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
00964 (*i)->print_decl(out) ;
00965 }
00966
00967 out << "} " << id2www(name) << ";\n" ;
00968
00969 return ;
00970 }
00971
00972 #if FILE_METHODS
00973
00983 void
00984 DDS::print_constrained(FILE *out)
00985 {
00986 fprintf(out, "Dataset {\n") ;
00987
00988 for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
00989
00990
00991
00992 (*i)->print_decl(out, " ", true, false, true) ;
00993 }
00994
00995 fprintf(out, "} %s;\n", id2www(name).c_str()) ;
00996
00997 return;
00998 }
00999 #endif
01000
01011 void
01012 DDS::print_constrained(ostream &out)
01013 {
01014 out << "Dataset {\n" ;
01015
01016 for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
01017
01018
01019
01020 (*i)->print_decl(out, " ", true, false, true) ;
01021 }
01022
01023 out << "} " << id2www(name) << ";\n" ;
01024
01025 return;
01026 }
01027
01028 #if FILE_METHODS
01029 class VariablePrintXML : public unary_function<BaseType *, void>
01030 {
01031 FILE *d_out;
01032 bool d_constrained;
01033 public:
01034 VariablePrintXML(FILE *out, bool constrained)
01035 : d_out(out), d_constrained(constrained)
01036 {}
01037 void operator()(BaseType *bt)
01038 {
01039 bt->print_xml(d_out, " ", d_constrained);
01040 }
01041 };
01042
01053 void
01054 DDS::print_xml(FILE *out, bool constrained, const string &blob)
01055 {
01056 fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
01057
01058 fprintf(out, "<Dataset name=\"%s\"\n", id2xml(name).c_str());
01059
01060 fprintf(out, "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
01061
01062 fprintf(out,"method=\"FILE*\"\n");
01063 fprintf(out, "dap_major=\"%d\"\n", get_dap_major());
01064 fprintf(out, "dap_minor=\"%d\"\n", get_dap_minor());
01065
01066
01067
01068 if (get_dap_major() == 3 && get_dap_minor() == 2) {
01069 fprintf(out, "xmlns=\"%s\"\n", c_dap32_namespace.c_str());
01070
01071 fprintf(out, "xsi:schemaLocation=\"%s %s\">\n\n",
01072 c_dap32_namespace.c_str(), c_default_dap32_schema_location.c_str());
01073 }
01074 else {
01075 fprintf(out, "xmlns=\"%s\"\n", c_dap20_namespace.c_str());
01076 fprintf(out, "xsi:schemaLocation=\"%s %s\">\n\n",
01077 c_dap20_namespace.c_str(), c_default_dap20_schema_location.c_str());
01078 }
01079
01080
01081 d_attr.print_xml(out, " ", constrained);
01082
01083 fprintf(out, "\n");
01084
01085 for_each(var_begin(), var_end(), VariablePrintXML(out, constrained));
01086
01087 fprintf(out, "\n");
01088
01089
01090
01091 if (get_dap_major() == 2 && get_dap_minor() == 0) {
01092 fprintf(out, " <dataBLOB href=\"\"/>\n");
01093 }
01094 else if (!blob.empty()
01095 && (get_dap_major() == 3 && get_dap_minor() >= 2)
01096 || get_dap_major() >= 4) {
01097 fprintf(out, " <blob href=\"cid:%s\"/>\n", blob.c_str());
01098 }
01099
01100
01101 fprintf(out, "</Dataset>\n");
01102 }
01103 #endif
01104
01105 class VariablePrintXMLStrm : public unary_function<BaseType *, void>
01106 {
01107 ostream &d_out;
01108 bool d_constrained;
01109 public:
01110 VariablePrintXMLStrm(ostream &out, bool constrained)
01111 : d_out(out), d_constrained(constrained)
01112 {}
01113 void operator()(BaseType *bt)
01114 {
01115 bt->print_xml(d_out, " ", d_constrained);
01116 }
01117 };
01118
01129 void
01130 DDS::print_xml(ostream &out, bool constrained, const string &blob)
01131 {
01132 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ;
01133
01134 out << "<Dataset name=\"" << id2xml(name) << "\"\n" ;
01135
01136 out << "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" ;
01137
01138
01139
01140 if (get_dap_major() == 3 && get_dap_minor() == 2) {
01141 out << "xsi:schemaLocation=\"" << c_dap32_namespace
01142 << " " << c_default_dap32_schema_location << "\"\n" ;
01143
01144 out << "xmlns:grddl=\"http://www.w3.org/2003/g/data-view#\"\n";
01145 out << "grddl:transformation=\"" << grddl_transformation_dap32 <<"\"\n";
01146
01147 out << "xmlns=\"" << c_dap32_namespace << "\"\n" ;
01148 out << "xmlns:dap=\"" << c_dap32_namespace << "\"\n" ;
01149
01150 out << "dapVersion=\"" << get_dap_major() << "."
01151 << get_dap_minor() << "\"";
01152
01153 if (!get_request_xml_base().empty()) {
01154 out << "\n";
01155 out << "xmlns:xml=\"" << c_xml_namespace << "\"\n";
01156 out << "xml:base=\"" << get_request_xml_base() << "\"";
01157 }
01158
01159
01160 out << ">\n";
01161 }
01162 else {
01163 out << "xmlns=\"" << c_dap20_namespace << "\"\n" ;
01164 out << "xsi:schemaLocation=\"" << c_dap20_namespace
01165 << " " << c_default_dap20_schema_location << "\">\n\n" ;
01166 }
01167
01168 d_attr.print_xml(out, " ", constrained);
01169
01170 out << "\n" ;
01171
01172 for_each(var_begin(), var_end(), VariablePrintXMLStrm(out, constrained));
01173
01174 out << "\n" ;
01175
01176
01177
01178
01179
01180 if (get_dap_major() == 2 && get_dap_minor() == 0) {
01181 out << " <dataBLOB href=\"\"/>\n" ;
01182 }
01183 else if (!blob.empty()
01184 && (get_dap_major() == 3 && get_dap_minor() >= 2)
01185 || get_dap_major() >= 4) {
01186 out << " <blob href=\"cid:" << blob << "\"/>\n";
01187 }
01188
01189 out << "</Dataset>\n" ;
01190 }
01191
01192
01207 bool
01208 DDS::check_semantics(bool all)
01209 {
01210
01211 if (name == "") {
01212 cerr << "A dataset must have a name" << endl;
01213 return false;
01214 }
01215
01216 string msg;
01217 if (!unique_names(vars, name, "Dataset", msg))
01218 return false;
01219
01220 if (all)
01221 for (Vars_iter i = vars.begin(); i != vars.end(); i++)
01222 if (!(*i)->check_semantics(msg, true))
01223 return false;
01224
01225 return true;
01226 }
01227
01253 bool
01254 DDS::mark(const string &n, bool state)
01255 {
01256 BaseType::btp_stack *s = new BaseType::btp_stack;
01257
01258 DBG2(cerr << "DDS::mark: Looking for " << n << endl);
01259
01260 BaseType *variable = var(n, s);
01261 if (!variable) {
01262 DBG2(cerr << "Could not find variable " << n << endl);
01263 delete s; s = 0;
01264 return false;
01265 }
01266 variable->set_send_p(state);
01267
01268 DBG2(cerr << "DDS::mark: Set variable " << variable->name()
01269 << " (a " << variable->type_name() << ")" << endl);
01270
01271
01272
01273
01274
01275 while (!s->empty()) {
01276 s->top()->BaseType::set_send_p(state);
01277
01278 DBG2(cerr << "DDS::mark: Set variable " << s->top()->name()
01279 << " (a " << s->top()->type_name() << ")" << endl);
01280 string parent_name = (s->top()->get_parent()) ? s->top()->get_parent()->name(): "none";
01281 string parent_type = (s->top()->get_parent()) ? s->top()->get_parent()->type_name(): "none";
01282 DBG2(cerr << "DDS::mark: Parent variable " << parent_name << " (a " << parent_type << ")" << endl);
01283
01284 s->pop();
01285 }
01286
01287 delete s ; s = 0;
01288
01289 return true;
01290 }
01291
01297 void
01298 DDS::mark_all(bool state)
01299 {
01300 for (Vars_iter i = vars.begin(); i != vars.end(); i++)
01301 (*i)->set_send_p(state);
01302 }
01303
01311 void
01312 DDS::dump(ostream &strm) const
01313 {
01314 strm << DapIndent::LMarg << "DDS::dump - ("
01315 << (void *)this << ")" << endl ;
01316 DapIndent::Indent() ;
01317 strm << DapIndent::LMarg << "name: " << name << endl ;
01318 strm << DapIndent::LMarg << "filename: " << d_filename << endl ;
01319 strm << DapIndent::LMarg << "protocol major: " << d_dap_major << endl;
01320 strm << DapIndent::LMarg << "protocol minor: " << d_dap_minor << endl;
01321 strm << DapIndent::LMarg << "factory: " << (void *)d_factory << endl ;
01322
01323 strm << DapIndent::LMarg << "global attributes:" << endl ;
01324 DapIndent::Indent() ;
01325 d_attr.dump(strm) ;
01326 DapIndent::UnIndent() ;
01327
01328 if (vars.size()) {
01329 strm << DapIndent::LMarg << "vars:" << endl ;
01330 DapIndent::Indent() ;
01331 Vars_citer i = vars.begin() ;
01332 Vars_citer ie = vars.end() ;
01333 for (; i != ie; i++) {
01334 (*i)->dump(strm) ;
01335 }
01336 DapIndent::UnIndent() ;
01337 }
01338 else {
01339 strm << DapIndent::LMarg << "vars: none" << endl ;
01340 }
01341
01342 DapIndent::UnIndent() ;
01343 }
01344
01345 }