45#include "InternalErr.h"
46#include "XDRStreamMarshaller.h"
51#include "D4Attributes.h"
63void Grid::m_duplicate(
const Grid &s) { d_is_array_set = s.d_is_array_set; }
74Grid::Grid(
const string &n) :
Constructor(n, dods_grid_c), d_is_array_set(false) {}
87Grid::Grid(
const string &n,
const string &d) : Constructor(n, d, dods_grid_c), d_is_array_set(false) {}
90Grid::Grid(
const Grid &rhs) : Constructor(rhs) { m_duplicate(rhs); }
96BaseType *Grid::ptr_duplicate() {
return new Grid(*
this); }
98Grid &Grid::operator=(
const Grid &rhs) {
101 Constructor::operator=(rhs);
109void Grid::transform_to_dap4(D4Group *root, Constructor *container) {
110 DBG(cerr << __func__ <<
"() - BEGIN (name:" << name() <<
")(type:" <<
type_name() <<
")(root:'" << root->name()
111 <<
"':" << (
void *)root <<
")(container:'" << container->name() <<
"':" << (
void *)container <<
")"
114 vector<Array *> d4_map_arrays;
122 for (Map_iter i = map_begin(), e = map_end(); i != e; ++i) {
123 DBG(cerr << __func__ <<
"() - Processing Map Array: '" << (*i)->name() <<
"' (" << (
void *)(*i) <<
")"
130 Array *the_map_array;
131 Array *container_map_array =
static_cast<Array *
>(container->var((*i)->name()));
132 if (!container_map_array) {
133 DBG(cerr << __func__ <<
"() - No Map Array '" << (*i)->name() <<
"' present in the current DAP4 container ("
134 << container->name() <<
":" << (
void *)container <<
"). Let's fix that..." << endl;);
136 Array *root_map_array =
static_cast<Array *
>(root->var((*i)->name()));
137 if (!root_map_array) {
139 DBG(cerr << __func__ <<
"() - No Map Array '" << (*i)->name() <<
"' present in the root Group ("
140 << root->name() <<
":" << (
void *)root <<
"). Let's fix that..." << endl;);
142 (*i)->transform_to_dap4(root, container);
144 the_map_array =
static_cast<Array *
>(container->var((*i)->name()));
145 DBG(cerr << __func__ <<
"() - Transformed array '" << the_map_array->name() <<
"' to DAP4 Array ("
146 << (
void *)the_map_array <<
") added to container: '" << container->name() <<
"'" << endl;);
148 the_map_array = root_map_array;
149 DBG(cerr << __func__ <<
"() - Located Map Array '" << the_map_array->name() <<
"' ("
150 << (
void *)the_map_array <<
") present in the root group (" << root->name() <<
":"
151 << (
void *)root <<
")" << endl;);
154 the_map_array = container_map_array;
155 DBG(cerr << __func__ <<
"() - Located Map Array '" << the_map_array->name() <<
"' ("
156 << (
void *)the_map_array <<
") present in the current DAP4 container (" << container->name() <<
":"
157 << (
void *)container <<
")" << endl;);
160 d4_map_arrays.push_back(the_map_array);
164 array_var()->transform_to_dap4(root, container);
166 BaseType *btp = container->var(array_var()->name());
167 Array *coverage =
static_cast<Array *
>(btp);
168 DBG(cerr << __func__ <<
"() - Transformed and added DAP4 coverage Array '" << coverage->name()
169 <<
"' to parent container: '" << container->name() <<
"'" << endl;);
171 coverage->attributes()->transform_to_dap4(get_attr_table());
173 DBG(cerr << __func__ <<
"() - " <<
"Coverage Array '" << coverage->name() <<
"' attributes: " << endl;
174 XMLWriter xmlw; coverage->get_attr_table().print_dap4(xmlw); cerr << xmlw.get_doc() << endl;);
179 for (; d4aItr != end; d4aItr++) {
180 Array *the_map_array = *d4aItr;
186 D4Map *d4_map =
new D4Map(the_map_array->FQN(), the_map_array);
187 coverage->maps()->add_map(d4_map);
191 DBG(cerr << __func__ <<
"() - Added DAP4 Map Array: '" << d4_map->name() <<
"' (" << (
void *)d4_map->array()
192 <<
") to coverage: '" << coverage->name() <<
"'" << endl;);
194 DBG(cerr << __func__ <<
"() - END (grid:" << name() <<
")" << endl;);
202bool Grid::is_dap2_only_type() {
return true; }
216void Grid::add_var(
BaseType *bt, Part part) {
218 throw InternalErr(__FILE__, __LINE__,
"Passing NULL pointer as variable to be added.");
221 throw Error(
string(
"A method usable only with DAP2 variables was called on a DAP4 variable (")
226 if (part == array && d_is_array_set ) {
228 throw InternalErr(__FILE__, __LINE__,
229 "Error: Grid::add_var called with part==Array, but the array was already set!");
233 if (!
dynamic_cast<Array *
>(bt)) {
234 throw InternalErr(__FILE__, __LINE__,
"Grid::add_var(): object is not an Array!");
244 bt_clone = bt->ptr_duplicate();
245 set_array(
static_cast<Array *
>(bt_clone));
249 bt_clone = bt->ptr_duplicate();
250 bt_clone->set_parent(
this);
251 d_vars.push_back(bt_clone);
255 if (!d_is_array_set ) {
257 bt_clone = bt->ptr_duplicate();
258 set_array(
static_cast<Array *
>(bt_clone));
260 bt_clone = bt->ptr_duplicate();
261 bt_clone->set_parent(
this);
262 d_vars.push_back(bt_clone);
283void Grid::add_var_nocopy(
BaseType *bt, Part part) {
285 throw InternalErr(__FILE__, __LINE__,
"Passing NULL pointer as variable to be added.");
288 throw Error(
string(
"A method usable only with DAP2 variables was called on a DAP4 variable (")
293 if (part == array && d_is_array_set ) {
295 throw InternalErr(__FILE__, __LINE__,
296 "Error: Grid::add_var called with part==Array, but the array was already set!");
300 if (!
dynamic_cast<Array *
>(bt)) {
301 throw InternalErr(__FILE__, __LINE__,
"Grid::add_var(): object is not an Array!");
304 bt->set_parent(
this);
310 set_array(
static_cast<Array *
>(bt));
316 d_vars.push_back(bt);
320 if (!d_is_array_set ) {
323 set_array(
static_cast<Array *
>(bt));
325 d_vars.push_back(bt);
344void Grid::set_array(Array *p_new_arr) {
346 throw InternalErr(__FILE__, __LINE__,
"Grid::set_array(): Cannot set to null!");
350 if (p_new_arr == get_array()) {
354 p_new_arr->set_parent(
this);
360 if (d_vars.size() == 0) {
361 d_vars.push_back(p_new_arr);
362 }
else if (!d_is_array_set ) {
363 d_vars.insert(d_vars.begin(), p_new_arr);
367 d_vars[0] = p_new_arr;
370 d_is_array_set =
true;
373 d_array_var = p_new_arr;
376 d_array_var->set_parent(
this);
406Array *Grid::add_map(Array *p_new_map,
bool add_as_copy) {
408 throw InternalErr(__FILE__, __LINE__,
"Grid::add_map(): cannot have p_new_map null!");
411 p_new_map =
static_cast<Array *
>(p_new_map->ptr_duplicate());
413 p_new_map->set_parent(
this);
415 d_vars.push_back(p_new_map);
433Array *Grid::prepend_map(Array *p_new_map,
bool add_copy) {
435 p_new_map =
static_cast<Array *
>(p_new_map->ptr_duplicate());
438 p_new_map->set_parent(
this);
439 d_vars.insert(map_begin(), p_new_map);
447BaseType *Grid::array_var() {
return d_is_array_set ? *d_vars.begin() :
nullptr; }
452Array *Grid::get_array() {
return dynamic_cast<Array *
>(array_var()); }
455Grid::Map_iter Grid::map_begin() {
460 return d_is_array_set ? d_vars.begin() + 1 : d_vars.begin();
465Grid::Map_iter Grid::map_end() {
return d_vars.end(); }
468Grid::Map_riter Grid::map_rbegin() {
470 return d_vars.rbegin();
475Grid::Map_riter Grid::map_rend() {
return d_is_array_set ? d_vars.rend() - 1 : d_vars.rend(); }
480Grid::Map_iter Grid::get_map_iter(
int i) {
return d_is_array_set ? d_vars.begin() + 1 + i : d_vars.begin() + i; }
497int Grid::components(
bool constrained) {
501 comp = get_array()->send_p() ? 1 : 0;
503 for (Map_iter i = map_begin(); i != map_end(); i++) {
504 if ((*i)->send_p()) {
509 comp = d_vars.size();
520void Grid::transfer_attributes(AttrTable *at_container) {
521 DBG(cerr << __func__ <<
"() - BEGIN " <<
type_name() <<
" " << name()
522 <<
" (at_container:" << at_container->get_name() <<
":" << (
void *)at_container <<
")" << endl;);
525 AttrTable *at = at_container->get_attr_table(name());
527 DBG(cerr << __func__ <<
"() - Found AttrTable (" << at->get_name() <<
":" << (
void *)at <<
")" << endl;);
528 at->set_is_global_attribute(
false);
537 array_var()->transfer_attributes(at);
544 AttrTable *dvat = at->get_attr_table(array_var()->name());
546 dvat->set_is_global_attribute(
false);
549 Map_iter map = map_begin();
550 while (map != map_end()) {
551 (*map)->transfer_attributes(at);
558 AttrTable::Attr_iter at_p = at->attr_begin();
559 while (at_p != at->attr_end()) {
560 if (at->is_global_attribute(at_p)) {
561 DBG(cerr << __func__ <<
"() - " <<
"Adding unclaimed Attribute (" << at->get_type(at_p) <<
":"
562 << at->get_name(at_p) <<
":" << (
void *)(*map) <<
") from AttrTable (" << at->get_name() <<
":"
563 << (
void *)at <<
")" <<
" to the variable " <<
type_name() <<
" " << name() << endl;);
565 if (at->get_attr_type(at_p) == Attr_container)
566 get_attr_table().
append_container(
new AttrTable(*at->get_attr_table(at_p)), at->get_name(at_p));
568 get_attr_table().
append_attr(at->get_name(at_p), at->get_type(at_p), at->get_attr_vector(at_p),
569 (*at_p)->is_utf8_str);
575 DBG(cerr << __func__ <<
"() - No AttrTable named '" << name() <<
"' was found in at_container ("
576 << at_container->get_name() <<
":" << (
void *)at <<
")" << endl;);
578 DBG(cerr << __func__ <<
"() - END " <<
type_name() <<
" " << name() <<
" (at_container:" << at_container->get_name()
579 <<
":" << (
void *)at_container <<
")" << endl;);
601bool Grid::projection_yields_grid() {
607 Array *a = get_array();
616 if (components(
true) == 1)
619 Array::Dim_iter d = a->dim_begin();
620 Map_iter m = map_begin();
622 while (valid && d != a->dim_end() && m != map_end()) {
623 Array &map =
dynamic_cast<Array &
>(**m);
624 if (a->dimension_size(d,
true) && map.send_p()) {
627 Array::Dim_iter fd = map.dim_begin();
628 valid = map.dimension_start(fd,
true) == a->dimension_start(d,
true) &&
629 map.dimension_stop(fd,
true) == a->dimension_stop(d,
true) &&
630 map.dimension_stride(fd,
true) == a->dimension_stride(d,
true);
642void Grid::clear_constraint() {
643 get_array()->clear_constraint();
644 for (Map_iter m = map_begin(); m != map_end(); ++m)
645 dynamic_cast<Array &
>(*(*m)).clear_constraint();
648void Grid::print_decl(FILE *out,
string space,
bool print_semi,
bool constraint_info,
bool constrained) {
650 print_decl(oss, space, print_semi, constraint_info, constrained);
651 fwrite(oss.str().data(),
sizeof(
char), oss.str().length(), out);
654void Grid::print_decl(ostream &out,
string space,
bool print_semi,
bool constraint_info,
bool constrained) {
655 if (constrained && !
send_p())
659 if (constrained && !projection_yields_grid()) {
660 out << space <<
"Structure {\n";
662 get_array()->print_decl(out, space +
" ",
true, constraint_info, constrained);
664 for (Map_citer i = map_begin(); i != map_end(); i++) {
665 (*i)->print_decl(out, space +
" ",
true, constraint_info, constrained);
668 out << space <<
"} " <<
id2www(name());
674 out << space <<
" Array:\n";
675 get_array()->print_decl(out, space +
" ",
true, constraint_info, constrained);
677 out << space <<
" Maps:\n";
678 for (Map_citer i = map_begin(); i != map_end(); i++) {
679 (*i)->print_decl(out, space +
" ",
true, constraint_info, constrained);
682 out << space <<
"} " <<
id2www(name());
685 if (constraint_info) {
687 out <<
": Send True";
689 out <<
": Send False";
701void Grid::print_xml(FILE *out,
string space,
bool constrained) {
702 XMLWriter xml(space);
703 print_xml_writer(xml, constrained);
704 fwrite(xml.get_doc(),
sizeof(
char), xml.get_doc_size(), out);
710void Grid::print_xml(ostream &out,
string space,
bool constrained) {
711 XMLWriter xml(space);
712 print_xml_writer(xml, constrained);
713 out << xml.get_doc();
716class PrintGridFieldXMLWriter :
public unary_function<BaseType *, void> {
722 PrintGridFieldXMLWriter(XMLWriter &x,
bool c,
const string &t =
"Map") : d_xml(x), d_constrained(c), d_tag(t) {}
724 void operator()(BaseType *btp) {
725 Array *a =
dynamic_cast<Array *
>(btp);
727 throw InternalErr(__FILE__, __LINE__,
"Expected an Array.");
728 a->print_xml_writer_core(d_xml, d_constrained, d_tag);
732void Grid::print_xml_writer(XMLWriter &xml,
bool constrained) {
733 if (constrained && !
send_p())
736 if (constrained && !projection_yields_grid()) {
737 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar *)
"Structure") < 0)
738 throw InternalErr(__FILE__, __LINE__,
"Could not write Structure element");
741 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar *)
"name",
742 (
const xmlChar *)name().c_str()) < 0)
743 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
747 get_array()->print_xml_writer(xml, constrained);
749 for_each(map_begin(), map_end(), PrintGridFieldXMLWriter(xml, constrained,
"Array"));
751 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
752 throw InternalErr(__FILE__, __LINE__,
"Could not end Structure element");
756 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar *)
"Grid") < 0)
757 throw InternalErr(__FILE__, __LINE__,
"Could not write Grid element");
760 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar *)
"name",
761 (
const xmlChar *)name().c_str()) < 0)
762 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
766 get_array()->print_xml_writer(xml, constrained);
768 for_each(map_begin(), map_end(), PrintGridFieldXMLWriter(xml, constrained,
"Map"));
770 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
771 throw InternalErr(__FILE__, __LINE__,
"Could not end Grid element");
775void Grid::print_val(FILE *out,
string space,
bool print_decl_p) {
778 fwrite(oss.str().data(),
sizeof(
char), oss.str().length(), out);
781void Grid::print_val(ostream &out,
string space,
bool print_decl_p) {
783 print_decl(out, space,
false);
791 bool pyg = projection_yields_grid();
797 get_array()->print_val(out,
"",
false);
802 for (Map_citer i = map_begin(); i != map_end(); i++, (void)(i != map_end() && out <<
", ")) {
803 (*i)->print_val(out,
"",
false);
818bool Grid::check_semantics(
string &msg,
bool all) {
819 if (!BaseType::check_semantics(msg))
825 msg +=
"Null grid base array in `" + name() +
"'\n";
830 if (get_array()->type() != dods_array_c) {
831 msg +=
"Grid `" + name() +
"'s' member `" + get_array()->name() +
"' must be an array\n";
835 Array *av = (Array *)get_array();
838 if (!av->var()->is_simple_type()) {
839 msg +=
"The field variable `" + this->name() +
840 "' must be an array of simple type elements (e.g., int32, String)\n";
845 if ((
unsigned)d_vars.size() - 1 != av->dimensions()) {
847 "The number of map variables for grid `" + this->name() +
"' does not match the number of dimensions of `";
848 msg += av->name() +
"'\n";
852 const string array_var_name = av->name();
853 Array::Dim_iter asi = av->dim_begin();
854 for (Map_iter mvi = map_begin(); mvi != map_end(); mvi++, asi++) {
859 if (array_var_name == mv->name()) {
861 "Grid map variable `" + mv->name() +
"' conflicts with the grid array name in grid `" + name() +
"'\n";
865 if (mv->type() != dods_array_c) {
866 msg +=
"Grid map variable `" + mv->name() +
"' is not an array\n";
870 Array *mv_a = (Array *)mv;
873 if (!mv_a->var()->is_simple_type()) {
874 msg +=
"The field variable `" + this->name() +
875 "' must be an array of simple type elements (e.g., int32, String)\n";
880 if (mv_a->dimensions() != 1) {
881 msg +=
"Grid map variable `" + mv_a->name() +
"' must be only one dimension\n";
885 Array::Dim_iter mv_asi = mv_a->dim_begin();
886 int mv_a_size = mv_a->dimension_size(mv_asi);
887 int av_size = av->dimension_size(asi);
888 if (mv_a_size != av_size) {
889 msg +=
"Grid map variable `" + mv_a->name() +
"'s' size does not match the size of array variable '";
890 msg += get_array()->name() +
"'s' cooresponding dimension\n";
896 if (!get_array()->check_semantics(msg,
true))
898 for (Map_iter mvi = map_begin(); mvi != map_end(); mvi++) {
899 if (!(*mvi)->check_semantics(msg,
true)) {
916void Grid::dump(ostream &strm)
const {
917 strm << DapIndent::LMarg <<
"Grid::dump - (" << (
void *)
this <<
")" << endl;
919 Constructor::dump(strm);
921 DapIndent::UnIndent();
virtual AttrTable * append_container(const string &name)
Add a container to the attribute table.
virtual unsigned int append_attr(const string &name, const string &type, const string &value)
Add an attribute to the table.
void print_xml_writer(XMLWriter &xml)
top level DAP object to house generic methods
virtual string type_name() const
Returns the type of the class instance as a string.
virtual bool send_p()
Should this variable be sent?
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
string id2www(string in, const string &allowable)