28#include <unordered_set>
31#include <libdap/BaseType.h>
32#include <libdap/Array.h>
33#include <libdap/Type.h>
34#include <libdap/D4Dimensions.h>
35#include <libdap/D4Group.h>
36#include <libdap/D4BaseTypeFactory.h>
37#include <libdap/D4Enum.h>
38#include <libdap/D4EnumDefs.h>
39#include <libdap/D4Attributes.h>
40#include <libdap/D4Maps.h>
41#include <libdap/DMR.h>
42#include <libdap/util.h>
44#define PUGIXML_NO_XPATH
45#define PUGIXML_HEADER_ONLY
52#include "DmrppCommon.h"
53#include "DmrppArray.h"
54#include "DmrppD4Group.h"
56#include "DmrppRequestHandler.h"
57#include "DmrppChunkOdometer.h"
58#include "BESInternalError.h"
70#define TREAT_NAMESPACES_AS_LITERALS 1
76#define USE_CACHED_XML_NODE 1
78#define SUPPORT_FILL_VALUE_CHUNKS 1
81#define prolog std::string("DMZ::").append(__func__).append("() - ")
85using shape = std::vector<unsigned long long>;
88const std::set<std::string> DMZ::variable_elements{
"Byte",
"Int8",
"Int16",
"Int32",
"Int64",
"UInt8",
"UInt16",
"UInt32",
89 "UInt64",
"Float32",
"Float64",
"String",
"Structure",
"Sequence",
94static inline bool is_eq(
const char *value,
const char *key)
96#if TREAT_NAMESPACES_AS_LITERALS
97 return strcmp(value, key) == 0;
99 if (strcmp(value, key) == 0) {
103 const char* colon = strchr(value,
':');
104 return colon && strcmp(colon + 1, key) == 0;
110static inline bool has_dim_nodes(
const xml_node &var_node)
112 return var_node.child(
"Dim");
116static inline bool member_of(
const set<string> &elements_set,
const string &element_name)
118 return elements_set.find(element_name) != elements_set.end();
122static inline DmrppCommon *dc(BaseType *btp)
124 auto *dc =
dynamic_cast<DmrppCommon*
>(btp);
126 throw BESInternalError(
string(
"Expected a BaseType that was also a DmrppCommon instance (")
127 .append((btp) ? btp->name() :
"unknown").append(
")."), __FILE__, __LINE__);
148 std::ifstream stream(file_name);
155 pugi::xml_parse_result result = d_xml_doc.load(stream, pugi::parse_default | pugi::parse_ws_pcdata_single);
158 throw BESInternalError(
string(
"DMR++ parse error: ").append(result.description()), __FILE__, __LINE__);
160 if (!d_xml_doc.document_element())
173void DMZ::process_dataset(DMR *dmr,
const xml_node &xml_root)
176 int required_attrs_found = 0;
178 bool href_trusted =
false;
179 string dmrpp_version;
180 for (xml_attribute attr = xml_root.first_attribute(); attr; attr = attr.next_attribute()) {
181 if (is_eq(attr.name(),
"name")) {
182 ++required_attrs_found;
183 dmr->set_name(attr.value());
185 else if (is_eq(attr.name(),
"dapVersion")) {
186 dmr->set_dap_version(attr.value());
188 else if (is_eq(attr.name(),
"dmrVersion")) {
189 dmr->set_dmr_version(attr.value());
191 else if (is_eq(attr.name(),
"base")) {
192 dmr->set_request_xml_base(attr.value());
193 BESDEBUG(PARSER, prolog <<
"Dataset xml:base is set to '" << dmr->request_xml_base() <<
"'" << endl);
196 else if (is_eq(attr.name(),
"xmlns")) {
197 dmr->set_namespace(attr.value());
201 else if (is_eq(attr.name(),
"dmrpp:href")) {
202 href_attr = attr.value();
204 else if (is_eq(attr.name(),
"dmrpp:trust")) {
205 href_trusted = is_eq(attr.value(),
"true");
207 else if (is_eq(attr.name(),
"dmrpp:version")) {
208 dmrpp_version = attr.value();
213 if (dmrpp_version.empty()) {
214 DmrppRequestHandler::d_emulate_original_filter_order_behavior =
true;
217 auto dmrpp =
dynamic_cast<DMRpp*
>(dmr);
219 dmrpp->set_version(dmrpp_version);
223 if (required_attrs_found != 1)
224 throw BESInternalError(
"DMR++ XML dataset element missing one or more required attributes.", __FILE__, __LINE__);
226 d_dataset_elem_href.reset(
new http::url(href_attr, href_trusted));
234void DMZ::process_dimension(D4Group *grp,
const xml_node &dimension_node)
238 for (xml_attribute attr = dimension_node.first_attribute(); attr; attr = attr.next_attribute()) {
239 if (is_eq(attr.name(),
"name")) {
240 name_value = attr.value();
242 else if (is_eq(attr.name(),
"size")) {
243 size_value = attr.value();
247 if (name_value.empty() || size_value.empty())
248 throw BESInternalError(
"The required attribute 'name' or 'size' was missing from a Dimension element.", __FILE__, __LINE__);
252 auto *dimension =
new D4Dimension();
253 dimension->set_name(name_value);
254 dimension->set_size(size_value);
255 grp->dims()->add_dim_nocopy(dimension);
269void DMZ::process_dim(DMR *dmr, D4Group *grp, Array *array,
const xml_node &dim_node)
271 assert(array->is_vector_type());
275 for (xml_attribute attr = dim_node.first_attribute(); attr; attr = attr.next_attribute()) {
276 if (is_eq(attr.name(),
"name")) {
277 name_value = attr.value();
279 else if (is_eq(attr.name(),
"size")) {
280 size_value = attr.value();
284 if (name_value.empty() && size_value.empty())
285 throw BESInternalError(
"Either 'size' or 'name' must be used in a Dim element.", __FILE__, __LINE__);
286 if (!name_value.empty() && !size_value.empty())
287 throw BESInternalError(
"Only one of 'size' and 'name' are allowed in a Dim element, but both were used.", __FILE__, __LINE__);
289 if (!size_value.empty()) {
290 BESDEBUG(PARSER, prolog <<
"Processing nameless Dim of size: " << stoi(size_value) << endl);
291 array->append_dim(stoi(size_value));
293 else if (!name_value.empty()) {
294 BESDEBUG(PARSER, prolog <<
"Processing Dim with named Dimension reference: " << name_value << endl);
297 if (name_value[0] ==
'/')
298 dim = dmr->root()->find_dim(name_value);
301 dim = grp->find_dim(name_value);
304 throw BESInternalError(
"The dimension '" + name_value +
"' was not found while parsing the variable '" + array->name() +
"'.",__FILE__,__LINE__);
306 array->append_dim(dim);
310void DMZ::process_map(DMR *dmr, D4Group *grp, Array *array,
const xml_node &map_node)
312 assert(array->is_vector_type());
316 for (xml_attribute attr = map_node.first_attribute(); attr; attr = attr.next_attribute()) {
317 if (is_eq(attr.name(),
"name")) {
318 name_value = attr.value();
323 if (name_value[0] !=
'/')
324 name_value = grp->FQN() + name_value;
327 Array *map_source = dmr->root()->find_map_source(name_value);
341 array->maps()->add_map(
new D4Map(name_value, map_source));
358void DMZ::process_variable(DMR *dmr, D4Group *group, Constructor *parent,
const xml_node &var_node)
364 Type t = get_type(var_node.name());
366 assert(t != dods_group_c);
368 bool is_array_type = has_dim_nodes(var_node);
371 btp = add_array_variable(dmr, group, parent, t, var_node);
372 if (t == dods_structure_c || t == dods_sequence_c) {
373 assert(btp->type() == dods_array_c && btp->var()->type() == t);
375 parent =
dynamic_cast<Constructor*
>(btp->var());
377 for (
auto child = var_node.first_child(); child; child = child.next_sibling()) {
378 if (member_of(variable_elements, child.name()))
379 process_variable(dmr, group, parent, child);
384 btp = add_scalar_variable(dmr, group, parent, t, var_node);
385 if (t == dods_structure_c || t == dods_sequence_c) {
386 assert(btp->type() == t);
387 parent =
dynamic_cast<Constructor*
>(btp);
389 for (
auto child = var_node.first_child(); child; child = child.next_sibling()) {
390 if (member_of(variable_elements, child.name()))
391 process_variable(dmr, group, parent, child);
396 dc(btp)->set_xml_node(var_node);
406BaseType *DMZ::build_variable(DMR *dmr, D4Group *group,
Type t,
const xml_node &var_node)
408 assert(dmr->factory());
412 for (xml_attribute attr = var_node.first_attribute(); attr; attr = attr.next_attribute()) {
413 if (is_eq(attr.name(),
"name")) {
414 name_value = attr.value();
416 if (is_eq(attr.name(),
"enum")) {
417 enum_value = attr.value();
421 if (name_value.empty())
422 throw BESInternalError(
"The variable 'name' attribute was missing.", __FILE__, __LINE__);
424 BaseType *btp = dmr->factory()->NewVariable(t, name_value);
426 throw BESInternalError(
"Could not instantiate the variable ' "+ name_value +
"'.", __FILE__, __LINE__);
428 btp->set_is_dap4(
true);
430 if (t == dods_enum_c) {
431 if (enum_value.empty())
432 throw BESInternalError(
"The variable ' " + name_value +
"' lacks an 'enum' attribute.", __FILE__, __LINE__);
435 if (enum_value[0] ==
'/')
436 enum_def = dmr->root()->find_enum_def(enum_value);
438 enum_def = group->find_enum_def(enum_value);
441 throw BESInternalError(
"Could not find the Enumeration definition '" + enum_value +
"'.", __FILE__, __LINE__);
443 dynamic_cast<D4Enum&
>(*btp).set_enumeration(enum_def);
459BaseType *DMZ::add_scalar_variable(DMR *dmr, D4Group *group, Constructor *parent,
Type t,
const xml_node &var_node)
463 BaseType *btp = build_variable(dmr, group, t, var_node);
468 parent->add_var_nocopy(btp);
470 group->add_var_nocopy(btp);
489BaseType *DMZ::add_array_variable(DMR *dmr, D4Group *group, Constructor *parent,
Type t,
const xml_node &var_node)
493 BaseType *btp = build_variable(dmr, group, t, var_node);
496 auto *array =
static_cast<Array*
>(dmr->factory()->NewVariable(dods_array_c, btp->name()));
497 array->set_is_dap4(
true);
498 array->add_var_nocopy(btp);
504 for (
auto child = var_node.first_child(); child; child = child.next_sibling()) {
505 if (is_eq(child.name(),
"Dim")) {
506 process_dim(dmr, group, array, child);
508 else if (is_eq(child.name(),
"Map")) {
509 process_map(dmr, group, array, child);
514 parent->add_var_nocopy(array);
516 group->add_var_nocopy(array);
529void DMZ::process_group(DMR *dmr, D4Group *parent,
const xml_node &var_node)
532 for (xml_attribute attr = var_node.first_attribute(); attr; attr = attr.next_attribute()) {
533 if (is_eq(attr.name(),
"name")) {
534 name_value = attr.value();
538 if (name_value.empty())
539 throw BESInternalError(
"The required attribute 'name' was missing from a Group element.", __FILE__, __LINE__);
541 BaseType *btp = dmr->factory()->NewVariable(dods_group_c, name_value);
543 throw BESInternalError(
"Could not instantiate the Group '" + name_value +
"'.", __FILE__, __LINE__);
545 auto new_group =
dynamic_cast<DmrppD4Group*
>(btp);
549 new_group->set_is_dap4(
true);
552 new_group->set_parent(parent);
553 parent->add_group_nocopy(new_group);
556 new_group->set_xml_node(var_node);
560 for (
auto child = var_node.first_child(); child; child = child.next_sibling()) {
561 if (is_eq(child.name(),
"Dimension")) {
562 process_dimension(new_group, child);
564 else if (is_eq(child.name(),
"Group")) {
565 process_group(dmr, new_group, child);
567 else if (member_of(variable_elements, child.name())) {
568 process_variable(dmr, new_group,
nullptr, child);
580 auto xml_root_node = d_xml_doc.first_child();
582 process_dataset(dmr, xml_root_node);
584 auto root_group = dmr->root();
588 throw BESInternalError(
"Expected the root group to also be an instance of DmrppD4Group.", __FILE__, __LINE__);
590 dg->set_xml_node(xml_root_node);
592 for (
auto child = xml_root_node.first_child(); child; child = child.next_sibling()) {
593 if (is_eq(child.name(),
"Dimension")) {
594 process_dimension(dg, child);
596 else if (is_eq(child.name(),
"Group")) {
597 process_group(dmr, dg, child);
600 else if (member_of(variable_elements, child.name())) {
601 process_variable(dmr, dg,
nullptr, child);
614void DMZ::process_attribute(D4Attributes *attributes,
const xml_node &dap_attr_node)
618 for (xml_attribute attr = dap_attr_node.first_attribute(); attr; attr = attr.next_attribute()) {
619 if (is_eq(attr.name(),
"name")) {
620 name_value = attr.value();
622 if (is_eq(attr.name(),
"type")) {
623 type_value = attr.value();
627 if (name_value.empty() || type_value.empty())
628 throw BESInternalError(
"The required attribute 'name' or 'type' was missing from an Attribute element.", __FILE__, __LINE__);
630 if (type_value ==
"Container") {
632 auto *dap_attr_cont =
new D4Attribute(name_value, attr_container_c);
633 attributes->add_attribute_nocopy(dap_attr_cont);
638 if (dap_attr_node.first_child()) {
639 for (
auto attr_node: dap_attr_node.children(
"Attribute")) {
640 process_attribute(dap_attr_cont->attributes(), attr_node);
644 else if (type_value ==
"OtherXML") {
649 auto *attribute =
new D4Attribute(name_value, StringToD4AttributeType(type_value));
650 attributes->add_attribute_nocopy(attribute);
652 for (
auto value_elem = dap_attr_node.first_child(); value_elem; value_elem = value_elem.next_sibling()) {
653 if (is_eq(value_elem.name(),
"Value")) {
654 attribute->add_value(value_elem.child_value());
677void DMZ::build_basetype_chain(BaseType *btp, stack<BaseType*> &bt)
679 auto parent = btp->get_parent();
683 if (parent && !(parent->type() == dods_group_c && parent->get_parent() ==
nullptr))
684 build_basetype_chain(parent, bt);
687xml_node DMZ::get_variable_xml_node_helper(
const xml_node &, stack<BaseType*> &)
689#if !USE_CACHED_XML_NODE
696 if (bt.top()->type() == dods_array_c && bt.top()->var()->is_constructor_type())
702 string type_name = bt.top()->type() == dods_array_c ? bt.top()->var()->type_name(): bt.top()->type_name();
703 string var_name = bt.top()->name();
707 for (
auto node = parent_node.child(type_name.c_str()); node; node = node.next_sibling()) {
708 for (xml_attribute attr = node.first_attribute(); attr; attr = attr.next_attribute()) {
709 if (is_eq(attr.name(),
"name") && is_eq(attr.value(), var_name.c_str())) {
714 return get_variable_xml_node_helper(node, bt);
731xml_node DMZ::get_variable_xml_node(BaseType *btp)
733#if USE_CACHED_XML_NODE
734 auto node = dc(btp)->get_xml_node();
736 throw BESInternalError(
string(
"The xml_node for '").append(btp->name()).append(
"' was not recorded."), __FILE__, __LINE__);
744 build_basetype_chain(btp, bt);
746 xml_node dataset = d_xml_doc.first_child();
747 if (!dataset || !is_eq(dataset.name(),
"Dataset"))
750 auto node = get_variable_xml_node_helper(dataset, bt);
773DMZ::load_attributes(BaseType *btp)
775 if (dc(btp)->get_attributes_loaded())
778 load_attributes(btp, get_variable_xml_node(btp));
781 dc(btp)->set_attributes_loaded(
true);
783 switch (btp->type()) {
791 dc(btp->var())->set_attributes_loaded(
true);
798 case dods_structure_c:
799 case dods_sequence_c:
801 auto *c =
dynamic_cast<Constructor*
>(btp);
803 for (
auto i = c->var_begin(), e = c->var_end(); i != e; i++) {
804 dc(btp->var())->set_attributes_loaded(
true);
821DMZ::load_attributes(BaseType *btp, xml_node var_node)
const
823 if (dc(btp)->get_attributes_loaded())
831 auto attributes = btp->BaseType::attributes();
832 for (
auto child = var_node.first_child(); child; child = child.next_sibling()) {
833 if (is_eq(child.name(),
"Attribute")) {
834 process_attribute(attributes, child);
838 dc(btp)->set_attributes_loaded(
true);
846DMZ::load_attributes(Constructor *constructor)
848 load_attributes(constructor, get_variable_xml_node(constructor));
849 for (
auto i = constructor->var_begin(), e = constructor->var_end(); i != e; ++i) {
851 assert((*i)->type() != dods_group_c);
857DMZ::load_attributes(D4Group *group) {
859 if (group->get_parent() ==
nullptr) {
860 xml_node dataset = d_xml_doc.child(
"Dataset");
862 throw BESInternalError(
"Could not find the 'Dataset' element in the DMR++ XML document.", __FILE__, __LINE__);
863 load_attributes(group, dataset);
866 load_attributes(group, get_variable_xml_node(group));
869 for (
auto i = group->var_begin(), e = group->var_end(); i != e; ++i) {
874 assert((*i)->type() != dods_group_c);
878 for (
auto i = group->grp_begin(), e = group->grp_end(); i != e; ++i) {
883void DMZ::load_all_attributes(libdap::DMR *dmr)
885 assert(d_xml_doc !=
nullptr);
886 load_attributes(dmr->root());
906DMZ::process_compact(BaseType *btp,
const xml_node &compact)
910 auto char_data = compact.child_value();
912 throw BESInternalError(
"The dmrpp::compact is missing data values.",__FILE__,__LINE__);
914 std::vector <u_int8_t> decoded = base64::Base64::decode(char_data);
916 if (btp->type() != dods_array_c)
917 throw BESInternalError(
"The dmrpp::compact element must be the child of an array variable",__FILE__,__LINE__);
920 switch (btp->var()->type()) {
922 throw BESInternalError(
"DMR++ document fail: An Array may not be the template for an Array.", __FILE__, __LINE__);
939 btp->val2buf(
reinterpret_cast<void *
>(decoded.data()));
940 btp->set_read_p(
true);
945 std::string str(decoded.begin(), decoded.end());
946 auto *st =
static_cast<DmrppArray *
>(btp);
950 st->set_read_p(
true);
955 throw BESInternalError(
"Unsupported COMPACT storage variable type in the drmpp handler.", __FILE__, __LINE__);
966void DMZ::process_chunk(DmrppCommon *dc,
const xml_node &chunk)
const
972 string chunk_position_in_array;
974 bool href_trusted =
false;
976 for (xml_attribute attr = chunk.first_attribute(); attr; attr = attr.next_attribute()) {
977 if (is_eq(attr.name(),
"href")) {
980 else if (is_eq(attr.name(),
"trust") || is_eq(attr.name(),
"dmrpp:trust")) {
981 href_trusted = is_eq(attr.value(),
"true");
983 else if (is_eq(attr.name(),
"offset")) {
984 offset = attr.value();
986 else if (is_eq(attr.name(),
"nBytes")) {
989 else if (is_eq(attr.name(),
"chunkPositionInArray")) {
990 chunk_position_in_array = attr.value();
994 if (offset.empty() || size.empty())
995 throw BESInternalError(
"Both size and offset are required for a chunk node.", __FILE__, __LINE__);
998 shared_ptr<http::url> data_url(
new http::url(href, href_trusted));
999 dc->
add_chunk(data_url, dc->get_byte_order(), stoull(size), stoull(offset), chunk_position_in_array);
1002 dc->
add_chunk(d_dataset_elem_href, dc->get_byte_order(), stoull(size), stoull(offset), chunk_position_in_array);
1012void DMZ::process_cds_node(DmrppCommon *dc,
const xml_node &chunks)
1014 for (
auto child = chunks.child(
"dmrpp:chunkDimensionSizes"); child; child = child.next_sibling()) {
1015 if (is_eq(child.name(),
"dmrpp:chunkDimensionSizes")) {
1016 string sizes = child.child_value();
1022static void add_fill_value_information(DmrppCommon *dc,
const string &value_string, libdap::Type fv_type)
1031void DMZ::process_chunks(DmrppCommon *dc,
const xml_node &chunks)
const
1033 for (xml_attribute attr = chunks.first_attribute(); attr; attr = attr.next_attribute()) {
1034 if (is_eq(attr.name(),
"compressionType")) {
1037 else if (is_eq(attr.name(),
"fillValue")) {
1039 auto array =
dynamic_cast<libdap::Array*
>(dc);
1041 throw BESInternalError(
"Fill Value chunks are only supported for Arrays.", __FILE__, __LINE__);
1043 add_fill_value_information(dc, attr.value(), array->var()->type());
1045 else if (is_eq(attr.name(),
"byteOrder")) {
1051 process_cds_node(dc, chunks);
1054 for (
auto chunk = chunks.child(
"dmrpp:chunk"); chunk; chunk = chunk.next_sibling()) {
1055 if (is_eq(chunk.name(),
"dmrpp:chunk")) {
1056 process_chunk(dc, chunk);
1066vector<unsigned long long> DMZ::get_array_dims(Array *array)
1068 vector<unsigned long long> array_dim_sizes;
1069 for (
auto i= array->dim_begin(), e = array->dim_end(); i != e; ++i) {
1070 array_dim_sizes.push_back(array->dimension_size(i));
1073 return array_dim_sizes;
1086size_t DMZ::logical_chunks(
const vector <unsigned long long> &array_dim_sizes,
const DmrppCommon *dc)
1089 if (chunk_dim_sizes.size() != array_dim_sizes.size()) {
1091 oss <<
"Expected the chunk and array rank to match (chunk: " << chunk_dim_sizes.size() <<
", array: "
1092 << array_dim_sizes.size() <<
")";
1096 size_t num_logical_chunks = 1;
1097 auto i = array_dim_sizes.begin();
1098 for (
auto chunk_dim_size: chunk_dim_sizes) {
1099 auto array_dim_size = *i++;
1100 num_logical_chunks *= (size_t)ceil((
float)array_dim_size / (float)chunk_dim_size);
1103 return num_logical_chunks;
1120set< vector<unsigned long long> > DMZ::get_chunk_map(
const vector<shared_ptr<Chunk>> &chunks)
1122 set< vector<unsigned long long> > chunk_map;
1123 for (
auto const &chunk: chunks) {
1124 chunk_map.insert(chunk->get_position_in_array());
1138void DMZ::process_fill_value_chunks(DmrppCommon *dc,
const set<shape> &chunk_map,
const shape &chunk_shape,
1139 const shape &array_shape,
unsigned long long chunk_size)
1142 DmrppChunkOdometer odometer(array_shape, chunk_shape);
1144 const auto &s = odometer.indices();
1145 if (chunk_map.find(s) == chunk_map.end()) {
1150 }
while (odometer.next());
1163 if (dc(btp)->get_chunks_loaded())
1167 xml_node var_node = get_variable_xml_node(btp);
1168 if (var_node ==
nullptr)
1169 throw BESInternalError(
"Could not find location of variable in the DMR++ XML document.", __FILE__, __LINE__);
1173 int chunks_found = 0;
1174 int chunk_found = 0;
1175 int compact_found = 0;
1178 auto child = var_node.child(
"dmrpp:chunks");
1181 process_chunks(dc(btp), child);
1182 auto array =
dynamic_cast<Array*
>(btp);
1186 auto const &array_shape = get_array_dims(array);
1187 size_t num_logical_chunks = logical_chunks(array_shape, dc(btp));
1189 if (num_logical_chunks != dc(btp)->get_chunks_size()) {
1190 auto const &chunk_map = get_chunk_map(dc(btp)->get_immutable_chunks());
1194 unsigned long long chunk_size_bytes = array->var()->width();
1195 for (
auto dim_size: chunk_shape)
1196 chunk_size_bytes *= dim_size;
1197 process_fill_value_chunks(dc(btp), chunk_map, dc(btp)->get_chunk_dimension_sizes(),
1198 array_shape, chunk_size_bytes);
1203 else if (array && dc(btp)->get_immutable_chunks().empty()) {
1204 auto const &array_shape = get_array_dims(array);
1206 unsigned long long array_size_bytes = 1;
1207 for (
auto dim_size: array_shape)
1208 array_size_bytes *= dim_size;
1210 array_size_bytes *= array->var()->width();
1212 shape pia(0,array_shape.size());
1214 dcp->add_chunk(dcp->get_byte_order(), dcp->get_fill_value(), dcp->get_fill_value_type(), array_size_bytes, pia);
1219 auto chunk = var_node.child(
"dmrpp:chunk");
1222 process_chunk(dc(btp), chunk);
1225 auto compact = var_node.child(
"dmrpp:compact");
1228 process_compact(btp, compact);
1232 if (DmrppRequestHandler::d_require_chunks) {
1233 int elements_found = chunks_found + chunk_found + compact_found;
1234 if (elements_found != 1) {
1236 oss <<
"Expected chunk, chunks or compact information in the DMR++ data. Found " << elements_found
1237 <<
" types of nodes.";
1242 dc(btp)->set_chunks_loaded(
true);
exception thrown if internal error encountered
DMZ()=default
Build a DMZ without simultaneously parsing an XML document.
virtual void load_chunks(libdap::BaseType *btp)
Load the chunk information into a variable.
void parse_xml_doc(const std::string &filename)
Build the DOM tree for a DMR++ XML document.
virtual void build_thin_dmr(libdap::DMR *dmr)
populate the DMR instance as a 'thin DMR'
virtual void set_fill_value_string(const std::string &fv)
Set the fill value (using a string)
virtual libdap::Type get_fill_value_type() const
virtual std::string get_fill_value() const
virtual void set_uses_fill_value(bool ufv)
Set the uses_fill_value property.
virtual void parse_chunk_dimension_sizes(const std::string &chunk_dim_sizes_string)
Set the dimension sizes for a chunk.
virtual unsigned long add_chunk(std::shared_ptr< http::url > d_data_url, const std::string &byte_order, unsigned long long size, unsigned long long offset, const std::string &position_in_array)
Adds a chunk to the vector of chunk refs (byteStreams) and returns the size of the chunks internal ve...
void set_filter(const std::string &value)
Set the value of the filters property.
virtual void ingest_byte_order(const std::string &byte_order_string)
Parses the text content of the XML element chunks:byteOrder.
virtual const std::vector< unsigned long long > & get_chunk_dimension_sizes() const
The chunk dimension sizes held in a const vector.
virtual void set_fill_value_type(libdap::Type t)
Set the libdap data type to use with the fill value.
void set_compact(bool value)
Set the value of the compact property.