libdap++  Updated for version 3.11.7
Constructor.cc
Go to the documentation of this file.
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
5 // Access Protocol.
6 
7 // Copyright (c) 2002,2003 OPeNDAP, Inc.
8 // Author: James Gallagher <jgallagher@opendap.org>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 //
24 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25 
26 // (c) COPYRIGHT URI/MIT 1995-1999
27 // Please read the full copyright statement in the file COPYRIGHT_URI.
28 //
29 // Authors:
30 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
31 
32 
33 #include "config.h"
34 
35 #include <string>
36 #include <algorithm>
37 #include <functional>
38 
39 //#define DODS_DEBUG
40 
41 #include "Constructor.h"
42 #include "Grid.h"
43 
44 #include "debug.h"
45 #include "escaping.h"
46 #include "Error.h"
47 #include "InternalErr.h"
48 
49 
50 using namespace std;
51 
52 namespace libdap {
53 
54 // Private member functions
55 
56 void
57 Constructor::_duplicate(const Constructor &)
58 {}
59 
60 // Public member functions
61 
62 Constructor::Constructor(const string &n, const Type &t)
63  : BaseType(n, t)
64 {}
65 
76 Constructor::Constructor(const string &n, const string &d, const Type &t)
77  : BaseType(n, d, t)
78 {}
79 
80 Constructor::Constructor(const Constructor &rhs) : BaseType(rhs), _vars(0)
81 {}
82 
84 {}
85 
88 {
89  if (this == &rhs)
90  return *this;
91 
92  dynamic_cast<BaseType &>(*this) = rhs; // run BaseType=
93 
94  _duplicate(rhs);
95 
96  return *this;
97 }
98 
102 {
103  return _vars.begin() ;
104 }
105 
106 #if 0
107 
125 BaseType *
126 Constructor::find_hdf4_dimension_attribute_home(AttrTable::entry *source)
127 {
128  BaseType *btp;
129  string::size_type i = source->name.find("_dim_");
130  if (i != string::npos && (btp = var(source->name.substr(0, i)))) {
131  if (btp->is_vector_type()) {
132  return btp;
133  }
134  else if (btp->type() == dods_grid_c) {
135  // For a Grid, the hdf4 handler uses _dim_n for the n-th Map
136  // i+5 points to the character holding 'n'
137  int n = atoi(source->name.substr(i + 5).c_str());
138  DBG(cerr << "Found a Grid (" << btp->name() << ") and "
139  << source->name.substr(i) << ", extracted n: " << n << endl);
140  return *(dynamic_cast<Grid&>(*btp).map_begin() + n);
141  }
142  }
143 
144  return 0;
145 }
146 #endif
147 #if 0
148 
150 AttrTable *
151 Constructor::find_matching_container(AttrTable::entry *source,
152  BaseType **dest_variable)
153 {
154  // The attribute entry 'source' must be a container
155  if (source->type != Attr_container)
156  throw InternalErr(__FILE__, __LINE__, "Constructor::find_matching_container");
157 
158  // Use the name of the attribute container 'source' to figure out where
159  // to put its contents.
160  BaseType *btp;
161  if ((btp = var(source->name))) {
162  // ... matches a variable name? Use var's table
163  *dest_variable = btp;
164  return &btp->get_attr_table();
165  }
166  // As more special-case attribute containers come to light, add clauses
167  // here.
168  else if ((btp = find_hdf4_dimension_attribute_home(source))) {
169  // ... hdf4 dimension attribute? Make a sub table and use that.
170  // btp can only be an Array or a Grid Map (which is an array)
171  if (btp->get_parent()->type() == dods_grid_c) {
172  DBG(cerr << "Found a Grid" << endl);
173  *dest_variable = btp;
174  return &btp->get_attr_table();
175  }
176  else { // must be a plain Array
177  string::size_type i = source->name.find("_dim_");
178  string ext = source->name.substr(i + 1);
179  *dest_variable = btp;
180  return btp->get_attr_table().append_container(ext);
181  }
182  }
183  else {
184  // ... otherwise assume it's a global attribute.
185  AttrTable *at = get_attr_table().find_container(source->name);
186  if (!at) {
187  at = new AttrTable(); // Make a new global table if needed
188  get_attr_table().append_container(at, source->name);
189  }
190 
191  *dest_variable = 0;
192  return at;
193  }
194 }
195 #endif
196 #if 0
197 
214 void
215 Constructor::transfer_attributes(AttrTable::entry * entry)
216 {
217  DBG(cerr << "Constructor::transfer_attributes, variable: " << name() <<
218  endl);
219  DBG(cerr << "Working on the '" << entry->
220  name << "' container." << endl);
221  if (entry->type != Attr_container)
222  throw InternalErr(__FILE__, __LINE__,
223  "Constructor::transfer_attributes");
224 
225  AttrTable *source = entry->attributes;
226  BaseType *dest_variable = 0;
227  AttrTable *dest = find_matching_container(entry, &dest_variable);
228 
229  // foreach source attribute in the das_i container
230  AttrTable::Attr_iter source_p = source->attr_begin();
231  while (source_p != source->attr_end()) {
232  DBG(cerr << "Working on the '" << (*source_p)->
233  name << "' attribute" << endl);
234 
235  if ((*source_p)->type == Attr_container) {
236  if (dest_variable && dest_variable->is_constructor_type()) {
237  dynamic_cast <Constructor & >(*dest_variable).transfer_attributes(*source_p);
238  }
239  else {
240  dest->append_container(new AttrTable(*(*source_p)->attributes),
241  (*source_p)->name);
242  }
243  }
244  else {
245  dest->append_attr(source->get_name(source_p),
246  source->get_type(source_p),
247  source->get_attr_vector(source_p));
248  }
249 
250  ++source_p;
251  }
252 }
253 #endif
254 
265  AttrTable *at = at_container->get_attr_table(name());
266 
267  if (at) {
268  at->set_is_global_attribute(false);
269 
270  Vars_iter var = var_begin();
271  while (var != var_end()) {
272  try {
273  DBG(cerr << "Processing the attributes for: " << (*var)->name() << " a " << (*var)->type_name() << endl);
274  (*var)->transfer_attributes(at);
275  var++;
276  } catch (Error &e) {
277  DBG(cerr << "Got this exception: " << e.get_error_message() << endl);
278  var++;
279  throw e;
280  }
281  }
282 
283  // Trick: If an attribute that's within the container 'at' still has its
284  // is_global_attribute property set, then it's not really a global attr
285  // but instead an attribute that belongs to this Constructor.
286  AttrTable::Attr_iter at_p = at->attr_begin();
287  while (at_p != at->attr_end()) {
288  if (at->is_global_attribute(at_p)) {
289  if (at->get_attr_type(at_p) == Attr_container)
290  get_attr_table().append_container(new AttrTable(*at->get_attr_table(at_p)), at->get_name(at_p));
291  else
292  get_attr_table().append_attr(at->get_name(at_p), at->get_type(at_p), at->get_attr_vector(at_p));
293  }
294  at_p++;
295  }
296 
297  }
298 }
299 
304 {
305  return _vars.end() ;
306 }
307 
311 {
312  return _vars.rbegin();
313 }
314 
319 {
320  return _vars.rend();
321 }
322 
328 {
329  return _vars.begin() + i;
330 }
331 
335 BaseType *
337 {
338  return *(_vars.begin() + i);
339 }
340 
341 #if FILE_METHODS
342 void
343 Constructor::print_decl(FILE *out, string space, bool print_semi,
344  bool constraint_info, bool constrained)
345 {
346  if (constrained && !send_p())
347  return;
348 
349  fprintf(out, "%s%s {\n", space.c_str(), type_name().c_str()) ;
350  for (Vars_citer i = _vars.begin(); i != _vars.end(); i++) {
351  (*i)->print_decl(out, space + " ", true,
352  constraint_info, constrained);
353  }
354  fprintf(out, "%s} %s", space.c_str(), id2www(name()).c_str()) ;
355 
356  if (constraint_info) { // Used by test drivers only.
357  if (send_p())
358  cout << ": Send True";
359  else
360  cout << ": Send False";
361  }
362 
363  if (print_semi)
364  fprintf(out, ";\n") ;
365 }
366 #endif
367 
368 void
369 Constructor::print_decl(ostream &out, string space, bool print_semi,
370  bool constraint_info, bool constrained)
371 {
372  if (constrained && !send_p())
373  return;
374 
375  out << space << type_name() << " {\n" ;
376  for (Vars_citer i = _vars.begin(); i != _vars.end(); i++) {
377  (*i)->print_decl(out, space + " ", true,
378  constraint_info, constrained);
379  }
380  out << space << "} " << id2www(name()) ;
381 
382  if (constraint_info) { // Used by test drivers only.
383  if (send_p())
384  out << ": Send True";
385  else
386  out << ": Send False";
387  }
388 
389  if (print_semi)
390  out << ";\n" ;
391 }
392 
393 #if FILE_METHODS
394 class PrintField : public unary_function<BaseType *, void>
395 {
396  FILE *d_out;
397  string d_space;
398  bool d_constrained;
399 public:
400  PrintField(FILE *o, string s, bool c)
401  : d_out(o), d_space(s), d_constrained(c)
402  {}
403 
404  void operator()(BaseType *btp)
405  {
406  btp->print_xml(d_out, d_space, d_constrained);
407  }
408 };
409 
413 void
414 Constructor::print_xml(FILE *out, string space, bool constrained)
415 {
416  if (constrained && !send_p())
417  return;
418 
419  bool has_attributes = false; // *** fix me
420  bool has_variables = (var_begin() != var_end());
421 
422  fprintf(out, "%s<%s", space.c_str(), type_name().c_str());
423  if (!name().empty())
424  fprintf(out, " name=\"%s\"", id2xml(name()).c_str());
425 
426  if (has_attributes || has_variables) {
427  fprintf(out, ">\n");
428 
429  get_attr_table().print_xml(out, space + " ", constrained);
430 
431  for_each(var_begin(), var_end(),
432  PrintField(out, space + " ", constrained));
433 
434  fprintf(out, "%s</%s>\n", space.c_str(), type_name().c_str());
435  }
436  else {
437  fprintf(out, "/>\n");
438  }
439 }
440 #endif
441 
442 class PrintFieldStrm : public unary_function<BaseType *, void>
443 {
444  ostream &d_out;
445  string d_space;
446  bool d_constrained;
447 public:
448  PrintFieldStrm(ostream &o, string s, bool c)
449  : d_out(o), d_space(s), d_constrained(c)
450  {}
451 
452  void operator()(BaseType *btp)
453  {
454  btp->print_xml(d_out, d_space, d_constrained);
455  }
456 };
457 
461 void
462 Constructor::print_xml(ostream &out, string space, bool constrained)
463 {
464  if (constrained && !send_p())
465  return;
466 
467  bool has_attributes = false; // *** fix me
468  bool has_variables = (var_begin() != var_end());
469 
470  out << space << "<" << type_name() ;
471  if (!name().empty())
472  out << " name=\"" << id2xml(name()) << "\"" ;
473 
474  if (has_attributes || has_variables) {
475  out << ">\n" ;
476 
477  get_attr_table().print_xml(out, space + " ", constrained);
478 
479  for_each(var_begin(), var_end(),
480  PrintFieldStrm(out, space + " ", constrained));
481 
482  out << space << "</" << type_name() << ">\n" ;
483  }
484  else {
485  out << "/>\n" ;
486  }
487 }
488 
489 class PrintFieldXMLWriter : public unary_function<BaseType *, void>
490 {
491  XMLWriter &d_xml;
492  bool d_constrained;
493 public:
494  PrintFieldXMLWriter(XMLWriter &x, bool c)
495  : d_xml(x), d_constrained(c)
496  {}
497 
498  void operator()(BaseType *btp)
499  {
500  btp->print_xml_writer(d_xml, d_constrained);
501  }
502 };
503 
504 void
506 {
507  if (constrained && !send_p())
508  return;
509 
510  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)type_name().c_str()) < 0)
511  throw InternalErr(__FILE__, __LINE__, "Could not write " + type_name() + " element");
512 
513  if (!name().empty())
514  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0)
515  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
516 
517  bool has_attributes = false; // FIXME
518  bool has_variables = (var_begin() != var_end());
519  if (has_attributes || has_variables) {
521 
522  for_each(var_begin(), var_end(), PrintFieldXMLWriter(xml, constrained));
523  }
524 
525  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
526  throw InternalErr(__FILE__, __LINE__, "Could not end " + type_name() + " element");
527 }
528 
541 bool
543 {
544  return false;
545 }
546 
555 void
556 Constructor::dump(ostream &strm) const
557 {
558  strm << DapIndent::LMarg << "Constructor::dump - ("
559  << (void *)this << ")" << endl ;
561  BaseType::dump(strm) ;
562  strm << DapIndent::LMarg << "vars: " << endl ;
564  Vars_citer i = _vars.begin() ;
565  Vars_citer ie = _vars.end() ;
566  for (; i != ie; i++) {
567  (*i)->dump(strm) ;
568  }
571 }
572 
573 } // namespace libdap
574