47 #include "D4Attributes.h"
49 #include "D4Dimensions.h"
52 #include "D4EnumDefs.h"
54 #include "XMLWriter.h"
58 #include "InternalErr.h"
60 #include "DapIndent.h"
66 Array::dimension::dimension(D4Dimension *d) : dim(d), use_sdim_for_slice(true)
78 Array::_duplicate(
const Array &a)
84 d_maps =
new D4Maps(*(a.d_maps));
108 for (
Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
112 length *= (*i).c_size > 0 ? (*i).c_size : 1;
139 :
Vector(n, 0, dods_array_c, is_dap4), d_maps(0)
158 :
Vector(n, d, 0, dods_array_c, is_dap4), d_maps(0)
178 return new Array(*
this);
182 Array::operator=(
const Array &rhs)
187 dynamic_cast<Vector &
>(*this) = rhs;
197 DBG(cerr << __func__ <<
"() - BEGIN (array:" <<
name() <<
")" << endl;);
202 DBG(cerr << __func__ <<
"() - Already DAP4 type: Just making a copy and adding to container. " << endl;);
204 DBG(cerr << __func__ <<
"() - END (Already DAP4 type)" << endl;);
212 for (
Array::Dim_iter dap2_dim = dest->dim_begin(), e = dest->dim_end(); dap2_dim != e; ++dap2_dim) {
213 if (!(*dap2_dim).name.empty()) {
214 DBG(cerr << __func__ <<
"() - Processing the array dimension '" << (*dap2_dim).name <<
"'" << endl;);
217 D4Dimension *d4_dim = root_dims->find_dim((*dap2_dim).name);
219 d4_dim =
new D4Dimension((*dap2_dim).name, (*dap2_dim).size);
221 DBG(cerr << __func__ <<
"() -" <<
222 " Added NEW D4Dimension '"<< d4_dim->name() <<
"' (" <<
223 (
void *)d4_dim <<
") to root->dims()"<< endl;);
226 DBG(cerr << __func__ <<
"() -" <<
227 " Using Existing D4Dimension '"<< d4_dim->name() <<
"' (" <<
228 (
void *)d4_dim <<
")"<< endl;);
230 if (d4_dim->size() != (
unsigned long) (*dap2_dim).size) {
242 d4_dim =
new D4Dimension((*dap2_dim).name +
"_" +
name(), (*dap2_dim).size);
243 DBG(cerr << __func__ <<
"() -" <<
244 " Utilizing Name/Size Conflict Naming Artifice. name'"<< d4_dim->name() <<
"' (" <<
245 (
void *)d4_dim <<
")"<< endl;);
251 (*dap2_dim).dim = d4_dim;
258 dest->set_is_dap4(
true);
260 DBG(cerr << __func__ <<
"() - END (array:" <<
name() <<
")" << endl;);
263 bool Array::is_dap2_grid(){
264 bool is_grid =
false;
266 DBG( cerr << __func__ <<
"() - Array '"<<
name() <<
"' is DAP4 object!" << endl;)
267 D4Maps *d4_maps = this->maps();
268 is_grid = d4_maps->size();
270 DBG( cerr << __func__ <<
"() - Array '"<<
name() <<
"' has D4Maps." << endl;)
272 D4Maps::D4MapsIter i = d4_maps->map_begin();
273 D4Maps::D4MapsIter e = d4_maps->map_end();
275 DBG( cerr << __func__ <<
"() - Map '"<< (*i)->array()->name() <<
" has " << (*i)->array()->_shape.size() <<
" dimension(s)." << endl;)
276 if((*i)->array()->_shape.size() > 1){
286 DBG( cerr << __func__ <<
"() - Array '"<<
name() <<
"' has no D4Maps." << endl;)
289 DBG( cerr << __func__ <<
"() - is_grid: "<< (is_grid?
"true":
"false") << endl;)
308 std::vector<BaseType *> *
310 DBG(cerr << __func__ <<
"() - BEGIN Array '"<<
name() <<
"'" << endl;);
318 DBG(cerr << __func__ <<
"() - Array '"<<
name() <<
"' is dap2 Grid!" << endl;);
322 g->set_array(grid_array);
333 g->set_attr_table(at);
336 D4Maps *d4_maps = this->maps();
337 vector<BaseType *> dropped_maps;
338 D4Maps::D4MapsIter miter = d4_maps->map_begin();
339 D4Maps::D4MapsIter end = d4_maps->map_end();
340 for( ; miter!=end; miter++){
341 D4Map *d4_map = (*miter);
342 Array *d4_map_array =
const_cast<Array*
>(d4_map->array());
343 vector<BaseType *> *d2_result = d4_map_array->
transform_to_dap2(&(g->get_attr_table()));
345 if(d2_result->size()>1)
346 throw Error(internal_error,
string(__func__)+
"() - ERROR: D4Map Array conversion resulted in multiple DAP2 objects.");
349 Array *d2_map_array =
dynamic_cast<Array *
>((*d2_result)[0]);
352 throw Error(internal_error,
string(__func__)+
"() - ERROR: DAP2 array from D4Map Array conversion has more than 1 dimension.");
354 g->add_map(d2_map_array,
false);
356 DBG( cerr << __func__ <<
"() - " <<
357 "DAS For Grid Map '" << d2_map_array->
name() <<
"':" << endl;
361 throw Error(internal_error,
string(__func__)+
"() - Unable to interpret returned DAP2 content.");
366 dropped_maps.push_back(d4_map_array);
371 if(!dropped_maps.empty()){
373 AttrTable *dv_table = Constructor::make_dropped_vars_attr_table(&dropped_maps);
374 dest->get_attr_table().append_container(dv_table,dv_table->
get_name());
379 DBG( cerr << __func__ <<
"() - Array '"<<
name() <<
"' is not a Grid!" << endl);
380 BaseType *proto = this->prototype();
381 switch(proto->
type()){
398 dest->set_attr_table(*attrs);
399 dest->set_is_dap4(
false);
401 DBG( cerr << __func__ <<
"() - " <<
402 "DAS for new Array '" << dest->name() <<
"':" << endl;
416 vector<BaseType *> *result;
418 result =
new vector<BaseType *>();
419 result->push_back(dest);
424 DBG( cerr << __func__ <<
"() - END Array '"<<
name() <<
"'" << endl;);
442 std::vector<dimension>::iterator i = _shape.begin(), e = _shape.end();
445 while (old_i != old_e) {
446 if ((*i).dim == *old_i) {
447 (*i).dim = new_dims->find_dim((*old_i)->name());
486 if (v && v->
type() == dods_array_c) {
508 if (v && v->
type() == dods_array_c) {
510 Vector::add_var_nocopy(a.
var());
519 Vector::add_var_nocopy(v);
562 _shape.insert(_shape.begin(), d);
572 _shape.insert(_shape.begin(), d);
594 std::vector<dimension>::iterator i = _shape.begin(), e = _shape.end();
597 if(d.
name == oldName){
598 DBG(cerr <<
"Old name = " << d.
name <<
" newName = " << newName << endl);
616 for (
Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
618 (*i).stop = (*i).size - 1;
620 (*i).c_size = (*i).size;
644 static const char *array_sss = \
645 "Invalid constraint parameters: At least one of the start, stride or stop \n\
646 specified do not match the array variable.";
682 if (start >= d.
size || stop >= d.
size || stride > d.
size || stride <= 0)
683 throw Error(malformed_expr, array_sss);
685 if (((stop - start) / stride + 1) > d.
size)
686 throw Error(malformed_expr, array_sss);
692 d.
c_size = (stop - start) / stride + 1;
694 DBG(cerr <<
"add_constraint: c_size = " << d.
c_size << endl);
706 if (dim->constrained())
707 add_constraint(i, dim->c_start(), dim->c_stride(), dim->c_stop());
709 dim->set_used_by_projected_var(
true);
713 d.use_sdim_for_slice =
true;
720 return _shape.begin() ;
727 return _shape.end() ;
743 return _shape.size();
768 if (!_shape.empty()) {
799 return (!_shape.empty()) ? (*i).start : 0;
823 return (!_shape.empty()) ? (*i).stop : 0;
848 return (!_shape.empty()) ? (*i).stride : 0;
871 "*This* array has no dimensions.");
876 Array::dimension_D4dim(Dim_iter i)
878 return (!_shape.empty()) ? (*i).dim : 0;
884 if (!d_maps) d_maps =
new D4Maps(
this);
906 for (
Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
914 class PrintD4ArrayDimXMLWriter:
public unary_function<Array::dimension&, void> {
921 PrintD4ArrayDimXMLWriter(XMLWriter &xml,
bool c) : xml(xml), d_constrained(c) { }
923 void operator()(Array::dimension &d)
929 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar*)
"Dim") < 0)
930 throw InternalErr(__FILE__, __LINE__,
"Could not write Dim element");
932 string name = (d.dim) ? d.dim->fully_qualified_name() : d.name;
935 if (!d_constrained && !name.empty()) {
936 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"name", (
const xmlChar*) name.c_str())
937 < 0)
throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
939 else if (d.use_sdim_for_slice) {
940 assert(!name.empty());
941 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"name", (
const xmlChar*) name.c_str())
942 < 0)
throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
946 size << (d_constrained ? d.c_size : d.size);
947 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"size",
948 (
const xmlChar*) size.str().c_str()) < 0)
949 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
952 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
953 throw InternalErr(__FILE__, __LINE__,
"Could not end Dim element");
957 class PrintD4ConstructorVarXMLWriter:
public unary_function<BaseType*, void> {
961 PrintD4ConstructorVarXMLWriter(XMLWriter &xml,
bool c) : xml(xml), d_constrained(c) { }
963 void operator()(BaseType *btp)
965 btp->print_dap4(xml, d_constrained);
969 class PrintD4MapXMLWriter:
public unary_function<D4Map*, void> {
973 PrintD4MapXMLWriter(XMLWriter &xml) : xml(xml) { }
975 void operator()(D4Map *m)
989 if (constrained && !
send_p())
return;
991 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar*)
var()->
type_name().c_str()) < 0)
995 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"name", (
const xmlChar*)
name().c_str()) < 0)
996 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
999 if (
var()->
type() == dods_enum_c) {
1001 string path = e->enumeration()->name();
1002 if (e->enumeration()->parent()) {
1004 path =
static_cast<D4Group*
>(e->enumeration()->parent()->parent())->
FQN() + path;
1006 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"enum", (
const xmlChar*)path.c_str()) < 0)
1007 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for enum");
1012 for_each(c.
var_begin(), c.
var_end(), PrintD4ConstructorVarXMLWriter(xml, constrained));
1017 for_each(
dim_begin(),
dim_end(), PrintD4ArrayDimXMLWriter(xml, constrained));
1021 for_each(maps()->map_begin(), maps()->map_end(), PrintD4MapXMLWriter(xml));
1023 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1046 bool constraint_info,
bool constrained)
1049 print_decl(oss, space, print_semi, constraint_info, constrained);
1050 fwrite(oss.str().data(),
sizeof(
char), oss.str().length(), out);
1070 void Array::print_decl(ostream &out,
string space,
bool print_semi,
bool constraint_info,
bool constrained)
1072 if (constrained && !
send_p())
return;
1075 var()->
print_decl(out, space,
false, constraint_info, constrained);
1077 for (
Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
1079 if ((*i).name !=
"") {
1080 out <<
id2www((*i).name) <<
" = ";
1083 out << (*i).c_size <<
"]";
1086 out << (*i).size <<
"]";
1102 print_xml_writer_core(xml, constrained,
"Array");
1103 fwrite(xml.get_doc(),
sizeof(
char), xml.get_doc_size(), out);
1113 print_xml_writer_core(xml, constrained,
"Array");
1114 out << xml.get_doc();
1124 print_xml_writer_core(xml, constrained,
"Map");
1125 fwrite(xml.get_doc(),
sizeof(
char), xml.get_doc_size(), out);
1135 print_xml_writer_core(xml, constrained,
"Map");
1136 out << xml.get_doc();
1146 print_xml_writer_core(xml, constrained, tag);
1147 fwrite(xml.get_doc(),
sizeof(
char), xml.get_doc_size(), out);
1157 print_xml_writer_core(xml, constrained, tag);
1158 out << xml.get_doc();
1164 print_xml_writer_core(xml, constrained,
"Array");
1168 Array::print_as_map_xml_writer(
XMLWriter &xml,
bool constrained)
1170 print_xml_writer_core(xml, constrained,
"Map");
1173 class PrintArrayDimXMLWriter :
public unary_function<Array::dimension&, void>
1178 PrintArrayDimXMLWriter(XMLWriter &xml,
bool c) : xml(xml), d_constrained(c) {}
1180 void operator()(Array::dimension &d)
1182 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar*)
"dimension") < 0)
1183 throw InternalErr(__FILE__, __LINE__,
"Could not write dimension element");
1185 if (!d.name.empty())
1186 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"name", (
const xmlChar*)d.name.c_str()) < 0)
1187 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1190 size << (d_constrained ? d.c_size : d.size);
1191 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"size", (
const xmlChar*)size.str().c_str()) < 0)
1192 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1194 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1195 throw InternalErr(__FILE__, __LINE__,
"Could not end dimension element");
1200 Array::print_xml_writer_core(XMLWriter &xml,
bool constrained,
string tag)
1202 if (constrained && !
send_p())
1205 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar*)tag.c_str()) < 0)
1206 throw InternalErr(__FILE__, __LINE__,
"Could not write " + tag +
" element");
1208 if (!
name().empty())
1209 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"name", (
const xmlChar*)
name().c_str()) < 0)
1210 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1215 string tmp_name = btp->name();
1217 btp->print_xml_writer(xml, constrained);
1218 btp->set_name(tmp_name);
1220 for_each(
dim_begin(),
dim_end(), PrintArrayDimXMLWriter(xml, constrained));
1222 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1223 throw InternalErr(__FILE__, __LINE__,
"Could not end " + tag +
" element");
1239 unsigned int shape[])
1242 unsigned int i =
print_array(oss, index, dims, shape);
1243 fwrite(oss.str().data(),
sizeof(
char), oss.str().length(), out);
1259 unsigned int Array::print_array(ostream &out,
unsigned int index,
unsigned int dims,
unsigned int shape[])
1265 if (shape[0] >= 1) {
1266 for (
unsigned i = 0; i < shape[0] - 1; ++i) {
1291 for (
unsigned i = 0; i < shape[0] - 1; ++i) {
1292 index =
print_array(out, index, dims - 1, shape + 1);
1296 index =
print_array(out, index, dims - 1, shape + 1);
1310 fwrite(oss.str().data(),
sizeof(
char), oss.str().length(), out);
1327 unsigned int *shape =
new unsigned int[
dimensions(
true)];
1328 unsigned int index = 0;
1329 for (
Dim_iter i = _shape.begin(); i != _shape.end() && index <
dimensions(
true); ++i)
1334 delete [] shape; shape = 0;
1356 msg =
"An array variable must have dimensions";
1372 strm << DapIndent::LMarg <<
"Array::dump - ("
1373 << (
void *)
this <<
")" << endl ;
1374 DapIndent::Indent() ;
1376 strm << DapIndent::LMarg <<
"shape:" << endl ;
1377 DapIndent::Indent() ;
1380 unsigned int dim_num = 0 ;
1381 for (; i != ie; i++) {
1382 strm << DapIndent::LMarg <<
"dimension " << dim_num++ <<
":"
1384 DapIndent::Indent() ;
1385 strm << DapIndent::LMarg <<
"name: " << (*i).name << endl ;
1386 strm << DapIndent::LMarg <<
"size: " << (*i).size << endl ;
1387 strm << DapIndent::LMarg <<
"start: " << (*i).start << endl ;
1388 strm << DapIndent::LMarg <<
"stop: " << (*i).stop << endl ;
1389 strm << DapIndent::LMarg <<
"stride: " << (*i).stride << endl ;
1390 strm << DapIndent::LMarg <<
"constrained size: " << (*i).c_size
1392 DapIndent::UnIndent() ;
1394 DapIndent::UnIndent() ;
1395 DapIndent::UnIndent() ;