31#include "AggregationUtil.h"
34#include "AggMemberDataset.h"
35#include "AggregationException.h"
39#include <libdap/Array.h>
40#include <libdap/AttrTable.h>
41#include <libdap/BaseType.h>
42#include <libdap/DataDDS.h>
43#include <libdap/DDS.h>
44#include <libdap/Grid.h>
46#include "BESStopWatch.h"
52using libdap::AttrTable;
53using libdap::BaseType;
54using libdap::Constructor;
62#define MODULE "agg_util"
65#define prolog_au string("AggregationUtil::").append(__func__).append("() - ")
67#define prolog_tlag string("TopLevelArrayGetter::").append(__func__).append("() - ")
69#define prolog_tlgdag string("TopLevelGridDataArrayGetter::").append(__func__).append("() - ")
71#define prolog_tlgmag string("TopLevelGridMapArrayGetter::").append(__func__).append("() - ")
76int AggregationUtil::d_last_added_cv_position = 0;
82ArrayGetterInterface::~ArrayGetterInterface()
89TopLevelArrayGetter::TopLevelArrayGetter() :
95TopLevelArrayGetter::~TopLevelArrayGetter()
103 return new TopLevelArrayGetter(*
this);
109 const libdap::Array*
const pConstraintTemplate,
const std::string& debugChannel)
const
112 BES_STOPWATCH_START(MODULE, prolog_tlag +
"Timing");
120 "Did not find a variable named \"" + name +
"\" at the top-level of the DDS!");
125 if (pBT->type() != libdap::dods_array_c) {
127 "The top-level DDS variable named \"" + name +
"\" was not of the expected type!"
128 " Expected:Array Found:" + pBT->type_name());
131 libdap::Array* pDatasetArray =
static_cast<libdap::Array*
>(pBT);
134 if (pConstraintTemplate) {
136 *pConstraintTemplate,
139 !(debugChannel.empty()),
144 pDatasetArray->set_send_p(
true);
145 pDatasetArray->set_in_selection(
true);
146 pDatasetArray->read();
148 return pDatasetArray;
154TopLevelGridDataArrayGetter::TopLevelGridDataArrayGetter() :
160TopLevelGridDataArrayGetter::~TopLevelGridDataArrayGetter()
168 return new TopLevelGridDataArrayGetter(*
this);
174 const libdap::Array*
const pConstraintTemplate,
const std::string& debugChannel)
const
176 BES_STOPWATCH_START(MODULE, prolog_tlgdag +
"Timing");
184 "Did not find a variable named \"" + name +
"\" at the top-level of the DDS!");
189 if (pBT->type() != libdap::dods_grid_c) {
191 "The top-level DDS variable named \"" + name +
"\" was not of the expected type!"
192 " Expected:Grid Found:" + pBT->type_name());
196 Grid* pDataGrid =
static_cast<Grid*
>(pBT);
197 Array* pDataArray =
static_cast<Array*
>(pDataGrid->array_var());
200 "The data Array var for variable name=\"" + name +
"\" was unexpectedly null!");
204 if (pConstraintTemplate) {
206 *pConstraintTemplate,
209 !(debugChannel.empty()),
219 pDataGrid->set_send_p(
true);
220 pDataGrid->set_in_selection(
true);
224 if (!pDataArray->read_p()) {
225 pDataArray->set_send_p(
true);
226 pDataArray->set_in_selection(
true);
236TopLevelGridMapArrayGetter::TopLevelGridMapArrayGetter(
const std::string& gridName) :
242TopLevelGridMapArrayGetter::~TopLevelGridMapArrayGetter()
250 return new TopLevelGridMapArrayGetter(*
this);
256 const libdap::Array*
const pConstraintTemplate,
const std::string& debugChannel)
const
258 BES_STOPWATCH_START(MODULE, prolog_tlgmag +
"Timing");
265 throw AggregationException(
"Did not find a variable named \"" + _gridName +
"\" at the top-level of the DDS!");
270 if (pBT->type() != libdap::dods_grid_c) {
272 "The top-level DDS variable named \"" + _gridName +
"\" was not of the expected type!"
273 " Expected:Grid Found:" + pBT->type_name());
277 Grid* pDataGrid =
static_cast<Grid*
>(pBT);
279 NCML_ASSERT_MSG(pMap,
280 "Expected to find the map with name " + arrayName +
" within the Grid " + _gridName +
" but failed to find it!");
283 pMap->set_send_p(
true);
284 pMap->set_in_selection(
true);
287 if (pConstraintTemplate) {
289 *pConstraintTemplate,
292 !(debugChannel.empty()),
307 VALID_PTR(pOutputUnion);
318 for (it = datasetsInOrder.begin(); it != endIt; ++it) {
319 const DDS* pDDS = *it;
325 const_cast<DDS*
>(pDDS)->get_attr_table());
336 AttrTable& fromTable =
const_cast<AttrTable&
>(fromTableIn);
337 AttrTable::Attr_iter endIt = fromTable.attr_end();
338 AttrTable::Attr_iter it;
339 for (it = fromTable.attr_begin(); it != endIt; ++it) {
340 const string& name = fromTable.get_name(it);
341 AttrTable::Attr_iter attrInOut;
346 "Union of AttrTable: an attribute named " << name <<
" already exist in output, skipping it..." << endl);
352 if (fromTable.is_container(it)) {
353 AttrTable* pOrigAttrContainer = fromTable.get_attr_table(it);
354 NCML_ASSERT_MSG(pOrigAttrContainer,
355 "AggregationUtil::mergeAttrTables(): expected non-null AttrTable for the attribute container: "
357 AttrTable* pClonedAttrContainer =
new AttrTable(*pOrigAttrContainer);
358 VALID_PTR(pClonedAttrContainer);
359 pOut->append_container(pClonedAttrContainer, name);
361 "Union of AttrTable: adding a deep copy of attribute=" << name <<
" to the merged output." << endl);
365 string type = fromTable.get_type(it);
366 vector<string>* pAttrTokens = fromTable.get_attr_vector(it);
367 VALID_PTR(pAttrTokens);
369 pOut->append_attr(name, type, pAttrTokens);
377 AttrTable& inTableSemanticConst =
const_cast<AttrTable&
>(inTable);
378 attr = inTableSemanticConst.simple_find(name);
379 return (attr != inTableSemanticConst.attr_end());
384 ConstDDSList::const_iterator endIt = datasetsInOrder.end();
385 ConstDDSList::const_iterator it;
386 for (it = datasetsInOrder.begin(); it != endIt; ++it) {
393 DDS& dds =
const_cast<DDS&
>(fromDDS);
394 DDS::Vars_iter endIt = dds.var_end();
396 for (it = dds.var_begin(); it != endIt; ++it) {
401 BESDEBUG(
"ncml",
"Variable name=" << var->name() <<
" wasn't in the union yet and was added." << endl);
405 "Variable name=" << var->name() <<
" was already in the union and was skipped." << endl);
417 d_last_added_cv_position = 0;
427 BESDEBUG(
"ncml2",
"AggregationUtil::addCopyOfVariableIfNameIsAvailable: " << varProto.name() << endl);
437 DDS::Vars_iter pos = pOutDDS->var_begin() + d_last_added_cv_position;
439 pOutDDS->insert_var(pos,
const_cast<BaseType*
>(&varProto));
441 ++d_last_added_cv_position;
444 pOutDDS->add_var(
const_cast<BaseType*
>(&varProto));
458 pOutDDS->del_var(varProto.name());
462 pOutDDS->add_var(
const_cast<BaseType*
>(&varProto));
469 DDS& dds =
const_cast<DDS&
>(dds_const);
470 DDS::Vars_iter endIt = dds.var_end();
472 for (it = dds.var_begin(); it != endIt; ++it) {
474 if (var && var->name() == name) {
482template<
class LibdapType>
488 return dynamic_cast<LibdapType*
>(pBT);
496void AggregationUtil::produceOuterDimensionJoinedArray(Array* pJoinedArray,
const std::string& joinedArrayName,
497 const std::string& newOuterDimName,
const std::vector<libdap::Array*>& fromVars,
bool copyData)
499 string funcName =
"AggregationUtil::createOuterDimensionJoinedArray:";
501 NCML_ASSERT_MSG(fromVars.size() > 0, funcName +
"Must be at least one Array in input!");
505 throw AggregationException(
506 funcName +
" The input arrays must all have the same data type and dimensions but do not!");
510 Array* templateArray = fromVars[0];
511 VALID_PTR(templateArray);
512 BaseType* templateVar = templateArray->var();
513 NCML_ASSERT_MSG(templateVar, funcName +
"Expected a non-NULL prototype BaseType in the first Array!");
516 pJoinedArray->add_var(templateVar);
518 pJoinedArray->set_name(joinedArrayName);
521 pJoinedArray->set_attr_table(templateArray->get_attr_table());
525 pJoinedArray->append_dim(fromVars.size(), newOuterDimName);
528 for (Array::Dim_iter it = templateArray->dim_begin(); it != templateArray->dim_end(); ++it) {
529 int dimSize = templateArray->dimension_size(it);
530 string dimName = templateArray->dimension_name(it);
531 pJoinedArray->append_dim(dimSize, dimName);
536 pJoinedArray->reserve_value_capacity(pJoinedArray->size());
538 joinArrayData(pJoinedArray, fromVars,
false,
545 bool enforceMatchingDimNames)
547 NCML_ASSERT(arrays.size() > 0);
549 Array* pTemplate = 0;
554 VALID_PTR(pTemplate);
570 Array& lhs =
const_cast<Array&
>(lhsC);
571 Array& rhs =
const_cast<Array&
>(rhsC);
572 return (lhs.var() && rhs.var() && lhs.var()->type() == rhs.var()->type());
578 Array& lhs =
const_cast<Array&
>(lhsC);
579 Array& rhs =
const_cast<Array&
>(rhsC);
583 if (lhs.dimensions() != rhs.dimensions()) {
588 Array::Dim_iter rhsIt = rhs.dim_begin();
589 for (Array::Dim_iter lhsIt = lhs.dim_begin(); lhsIt != lhs.dim_end(); (++lhsIt, ++rhsIt)) {
590 valid = (valid && (lhs.dimension_size(lhsIt) == rhs.dimension_size(rhsIt)));
593 valid = (valid && (lhs.dimension_name(lhsIt) == rhs.dimension_name(rhsIt)));
601 const std::string& collectVarName,
const ConstDDSList& datasetsInOrder)
603 unsigned int count = 0;
604 ConstDDSList::const_iterator endIt = datasetsInOrder.end();
605 ConstDDSList::const_iterator it;
606 for (it = datasetsInOrder.begin(); it != endIt; ++it) {
607 DDS* pDDS =
const_cast<DDS*
>(*it);
611 varArrays.push_back(pVar);
620 Array* pArr =
dynamic_cast<Array*
>(pBT);
621 if (pArr && (pArr->dimensions() == 1)) {
623 Array::Dim_iter it = pArr->dim_begin();
624 bool matches = (pArr->dimension_name(it) == pArr->name());
625 NCML_ASSERT_MSG((++it == pArr->dim_end()),
626 "Logic error: NCMLUtil::isCoordinateVariable(): expected one dimension from Array, but got more!");
635void AggregationUtil::joinArrayData(Array* pAggArray,
const std::vector<Array*>& varArrays,
636 bool reserveStorage,
bool clearDataAfterUse)
639 VALID_PTR(pAggArray->var());
640 NCML_ASSERT_MSG(pAggArray->var()->is_simple_type(),
641 "AggregationUtil::joinArrayData: the output Array is not of a simple type! Can't aggregate!");
644 if (reserveStorage) {
646 unsigned int totalLength = 0;
650 for (it = varArrays.begin(); it != endIt; ++it) {
653 totalLength += pArr->size();
657 pAggArray->reserve_value_capacity(totalLength);
661 unsigned int nextElt = 0;
662 vector<Array*>::const_iterator it;
663 vector<Array*>::const_iterator endIt = varArrays.end();
664 for (it = varArrays.begin(); it != endIt; ++it) {
667 NCML_ASSERT_MSG(pArr->var() && (pArr->var()->type() == pAggArray->var()->type()),
668 "AggregationUtil::joinArrayData: one of the arrays to join has different type than output! Can't aggregate!");
671 if (!pArr->read_p()) {
676 nextElt += pAggArray->set_value_slice_from_row_major_vector(*pArr, nextElt);
678 if (clearDataAfterUse) {
679 pArr->clear_local_data();
701 os <<
"Array dimensions: " << endl;
702 Array& theArray =
const_cast<Array&
>(fromArray);
704 Array::Dim_iter endIt = theArray.dim_end();
705 for (it = theArray.dim_begin(); it != endIt; ++it) {
706 Array::dimension d = *it;
707 os <<
"Dim = {" << endl;
708 os <<
"name=" << d.name << endl;
709 os <<
"size=" << d.size << endl;
712 os <<
"End Array dimensions." << endl;
717 os <<
"Array constraints: " << endl;
718 Array& theArray =
const_cast<Array&
>(rcArray);
720 Array::Dim_iter endIt = theArray.dim_end();
721 for (it = theArray.dim_begin(); it != endIt; ++it) {
722 Array::dimension d = *it;
723 os <<
"Dim = {" << endl;
724 os <<
"name=" << d.name << endl;
725 os <<
"start=" << d.start << endl;
726 os <<
"stride=" << d.stride << endl;
727 os <<
"stop=" << d.stop << endl;
730 os <<
"End Array constraints" << endl;
736 BESDEBUG(debugChannel,
"Printing constraints for Array: " << fromArray.name() <<
": " << oss.str() << endl);
738 BESDEBUG(debugChannel, oss.str() << endl);
742 bool skipFirstToDim,
bool printDebug ,
const std::string& debugChannel )
745 Array& fromArray =
const_cast<Array&
>(fromArrayConst);
748 pToArray->reset_constraint();
751 int skipDelta = ((skipFirstFromDim) ? (1) : (0));
754 if (skipFirstToDim) {
757 if (skipDelta < 0 || (pToArray->dimensions() + skipDelta !=
const_cast<Array&
>(fromArrayConst).dimensions())) {
759 "Mismatched dimensionalities!");
763 BESDEBUG(debugChannel,
764 "Printing constraints on fromArray name= " << fromArray.name() <<
" before transfer..." << endl);
771 Array::Dim_iter fromArrIt = fromArray.dim_begin();
772 Array::Dim_iter fromArrEndIt = fromArray.dim_end();
773 Array::Dim_iter toArrIt = pToArray->dim_begin();
774 for (; fromArrIt != fromArrEndIt; ++fromArrIt) {
775 if (skipFirstFromDim && (fromArrIt == fromArray.dim_begin())) {
778 if (skipFirstToDim) {
786 pToArray->add_constraint(toArrIt, fromArrIt->start, fromArrIt->stride, fromArrIt->stop);
791 BESDEBUG(debugChannel,
"Printing constrains on pToArray after transfer..." << endl);
800 DDS& dds =
const_cast<DDS&
>(ddsConst);
801 DDS::Vars_iter endIt = dds.var_end();
803 for (it = dds.var_begin(); it != endIt; ++it) {
805 if (var && var->name() == name) {
820 Constructor& varContainer =
const_cast<Constructor&
>(varContainerConst);
821 Constructor::Vars_iter endIt = varContainer.var_end();
822 Constructor::Vars_iter it;
823 for (it = varContainer.var_begin(); it != endIt; ++it) {
825 if (var && var->name() == name) {
845 libdap::Array* pArray(0);
846 switch (pBT->type()) {
847 case libdap::dods_array_c:
848 pArray =
static_cast<libdap::Array*
>(pBT);
851 case libdap::dods_grid_c:
852 pArray =
static_cast<Grid*
>(pBT)->get_array();
865 Grid& grid =
const_cast<Grid&
>(inGrid);
868 Grid::Map_iter endIt = grid.map_end();
869 for (it = grid.map_begin(); it != endIt; ++it) {
870 if ((*it)->name() == findName) {
871 pRet =
static_cast<Array*
>(*it);
880 const std::string& debugChannel)
882 BES_STOPWATCH_START(MODULE, prolog_au +
"Timing");
884 const libdap::DDS* pDDS = dataset.
getDDS();
885 NCML_ASSERT_MSG(pDDS,
"GridAggregateOnOuterDimension::read(): Got a null DataDDS "
886 "while loading dataset = " + dataset.
getLocation());
889 Array* pDatasetArray = arrayGetter.
readAndGetArray(varName, *pDDS, &constrainedTemplateArray, debugChannel);
890 NCML_ASSERT_MSG(pDatasetArray,
"In aggregation member dataset, failed to get the array! "
894 if (!pDatasetArray->read_p()) {
895 NCML_ASSERT_MSG(pDatasetArray->read_p(),
896 "AggregationUtil::addDatasetArrayDataToAggregationOutputArray: pDatasetArray was not read_p()!");
902 "Invalid aggregation! "
903 "AggregationUtil::addDatasetArrayDataToAggregationOutputArray: "
904 "We found the aggregation variable name=" + varName
905 +
" but it was not of the same type as the prototype variable!");
911 "Invalid aggregation! "
912 "AggregationUtil::addDatasetArrayDataToAggregationOutputArray: "
913 "We found the aggregation variable name=" + varName
914 +
" but it was not of the same shape as the prototype!");
918 if (constrainedTemplateArray.length() != pDatasetArray->length()) {
919 NCML_ASSERT_MSG(constrainedTemplateArray.length() == pDatasetArray->length(),
920 "AggregationUtil::addDatasetArrayDataToAggregationOutputArray: "
921 "The prototype array and the loaded dataset array size()'s were not equal, even "
922 "though their shapes matched. Logic problem.");
925 return pDatasetArray;
929 const Array& constrainedTemplateArray,
const std::string& varName,
AggMemberDataset& dataset,
932 BES_STOPWATCH_START(MODULE, prolog_au +
"Timing");
938 oOutputArray.set_value_slice_from_row_major_vector(*pDatasetArray, atIndex);
941 pDatasetArray->clear_local_data();
946 BaseType& fromVar =
const_cast<BaseType&
>(fromVarC);
958 pIntoVar->get_attr_table().erase();
961 pIntoVar->set_attr_table(finalAT);
virtual const libdap::DDS * getDDS()=0
const std::string & getLocation() const
static void addDatasetArrayDataToAggregationOutputArray(libdap::Array &oOutputArray, unsigned int atIndex, const libdap::Array &constrainedTemplateArray, const string &varName, AggMemberDataset &dataset, const ArrayGetterInterface &arrayGetter, const string &debugChannel)
static void printConstraintsToDebugChannel(const std::string &debugChannel, const libdap::Array &fromArray)
static void gatherMetadataChangesFrom(libdap::BaseType *pIntoVar, const libdap::BaseType &fromVar)
static LibdapType * findTypedVariableAtDDSTopLevel(const libdap::DDS &dds, const string &name)
static bool doTypesMatch(const libdap::Array &lhs, const libdap::Array &rhs)
static unsigned int collectVariableArraysInOrder(std::vector< libdap::Array * > &varArrays, const std::string &collectVarName, const ConstDDSList &datasetsInOrder)
static void transferArrayConstraints(libdap::Array *pToArray, const libdap::Array &fromArray, bool skipFirstFromDim, bool skipFirstToDim, bool printDebug=false, const std::string &debugChannel="agg_util")
static void printDimensions(std::ostream &os, const libdap::Array &fromArray)
static libdap::Array * readDatasetArrayDataForAggregation(const libdap::Array &constrainedTemplateArray, const std::string &varName, AggMemberDataset &dataset, const ArrayGetterInterface &arrayGetter, const std::string &debugChannel)
static void performUnionAggregation(libdap::DDS *pOutputUnion, const ConstDDSList &datasetsInOrder)
static libdap::BaseType * getVariableNoRecurse(const libdap::DDS &dds, const std::string &name)
static void unionAllVariablesInto(libdap::DDS *pOutputUnion, const ConstDDSList &datasetsInOrder)
static libdap::Array * getAsArrayIfPossible(libdap::BaseType *pBT)
static bool couldBeCoordinateVariable(libdap::BaseType *pBT)
static const libdap::Array * findMapByName(const libdap::Grid &inGrid, const std::string &findName)
static bool addCopyOfVariableIfNameIsAvailable(libdap::DDS *pOutDDS, const libdap::BaseType &varProto, bool add_at_top=false)
static void addOrReplaceVariableForName(libdap::DDS *pOutDDS, const libdap::BaseType &varProto)
static void unionAttrsInto(libdap::AttrTable *pOut, const libdap::AttrTable &fromTable)
static bool doShapesMatch(const libdap::Array &lhs, const libdap::Array &rhs, bool checkDimNames)
static bool findAttribute(const libdap::AttrTable &inTable, const string &name, libdap::AttrTable::Attr_iter &attr)
static void resetCVInsertionPosition()
static bool validateArrayTypesAndShapesMatch(const std::vector< libdap::Array * > &arrays, bool enforceMatchingDimNames)
static void printConstraints(std::ostream &os, const libdap::Array &fromArray)
static libdap::BaseType * findVariableAtDDSTopLevel(const libdap::DDS &dds, const string &name)
Helper class for temporarily hijacking an existing dhi to load a DDX response for one particular file...
virtual libdap::Array * readAndGetArray(const std::string &name, const libdap::DDS &dds, const libdap::Array *const pConstraintTemplate, const std::string &debugChannel) const =0
virtual libdap::Array * readAndGetArray(const std::string &name, const libdap::DDS &dds, const libdap::Array *const pConstraintTemplate, const std::string &debugChannel) const
virtual TopLevelArrayGetter * clone() const
virtual libdap::Array * readAndGetArray(const std::string &name, const libdap::DDS &dds, const libdap::Array *const pConstraintTemplate, const std::string &debugChannel) const
virtual TopLevelGridDataArrayGetter * clone() const
virtual TopLevelGridMapArrayGetter * clone() const
virtual libdap::Array * readAndGetArray(const std::string &name, const libdap::DDS &dds, const libdap::Array *const pConstraintTemplate, const std::string &debugChannel) const