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 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>
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 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
00983
00984
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
01011
01012
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
01060
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
01083
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
01132
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
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
01170
01171
01172
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
01200 bool
01201 DDS::check_semantics(bool all)
01202 {
01203
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
01265
01266
01267
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 }