33 #include <AttrTable.h>
41 #include <AttrTable.h>
80 , _gotVariableAggElement(false)
81 , _wasAggregatedMapAddedForJoinExistingGrid(false)
82 , _coordinateAxisType(
"")
90 , _dimName(proto._dimName)
91 , _recheckEvery(proto._recheckEvery)
92 , _parent(proto._parent)
95 , _aggVars(proto._aggVars)
96 , _gotVariableAggElement(false)
97 , _wasAggregatedMapAddedForJoinExistingGrid(false)
98 , _coordinateAxisType(
"")
102 if (!proto._datasets.empty())
105 "WARNING: AggregationElement copy ctor is deep copying all contained datasets! This might be memory and time intensive!");
109 _datasets.reserve(proto._datasets.size());
110 for (vector<NetcdfElement*>::const_iterator it = proto._datasets.begin();
111 it != proto._datasets.end();
117 NCML_ASSERT(_datasets.size() == proto._datasets.size());
119 _scanners.reserve(proto._scanners.size());
120 for (vector<ScanElement*>::const_iterator it = proto._scanners.begin();
121 it != proto._scanners.end();
127 NCML_ASSERT(_scanners.size() == proto._scanners.size());
132 BESDEBUG(
"ncml:memory",
"~AggregationElement called...");
137 _wasAggregatedMapAddedForJoinExistingGrid =
false;
140 while (!_datasets.empty())
143 _datasets.pop_back();
148 while (!_scanners.empty())
151 _scanners.pop_back();
188 "Got an <aggregation> = " +
toString() +
189 " at incorrect parse location. They can only be direct children of <netcdf>. Scope=" +
194 NCML_ASSERT_MSG(dataset,
"We expected a non-noll current dataset while processing AggregationElement::handleBegin() for " +
toString());
199 "Got <aggregation> = " +
toString() +
" but the enclosing dataset = " + dataset->
toString() +
200 " already had an aggregation set! There can be only one!");
214 "Got non-whitespace for content and didn't expect it. Element=" +
toString() +
" content=\"" +
223 BESDEBUG(
"ncml",
"Got AggregationElement::handleEnd(): Processing the aggregation!!" << endl);
227 BESDEBUG(
"ncml2",
" AggregationElement::handleEnd; isUnionAggregation" << endl);
232 BESDEBUG(
"ncml2",
" AggregationElement::handleEnd; isJoinNewAggregation" << endl);
237 BESDEBUG(
"ncml2",
" AggregationElement::handleEnd; isJoinExistingAggregation" << endl);
238 processJoinExisting();
240 else if (_type ==
"forecastModelRunCollection" ||
241 _type ==
"forecastModelSingleRunCollection")
244 "Sorry, we do not implement the forecastModelRunCollection aggregations in this version of the NCML Module!");
249 "Unknown aggregation type=" + _type +
" at scope=" +
_parser->getScopeString());
257 " type=\"" + _type +
"\"" +
266 return (_type ==
"joinNew");
272 return (_type ==
"union");
278 return (_type ==
"joinExisting");
285 BESDEBUG(
"ncml",
"AggregationElement: adding child dataset: " << pDataset->
toString() << endl);
289 _datasets.push_back(pDataset);
301 "Tried to add an aggregation variable twice: name=" + name +
302 " at scope=" +
_parser->getScopeString());
306 _aggVars.push_back(name);
307 BESDEBUG(
"ncml",
"Added aggregation variable name=" + name << endl);
317 for (; it != endIt; ++it)
334 for (; it != endIt; ++it)
346 return _aggVars.begin();
352 return _aggVars.end();
358 return _gotVariableAggElement;
364 _gotVariableAggElement =
true;
371 _scanners.push_back(pScanner);
379 BESDEBUG(
"ncml",
"AggregationElement::processParentDatasetComplete() called..." << endl);
381 if (_type ==
"joinNew")
383 processParentDatasetCompleteForJoinNew();
385 else if (_type ==
"joinExisting")
387 processParentDatasetCompleteForJoinExisting();
403 AggregationElement::processUnion()
405 BESDEBUG(
"ncml",
"Processing a union aggregation..." << endl);
414 vector<const DDS*> datasetsInOrder;
417 collectDatasetsInOrder(datasetsInOrder);
423 AggregationUtil::performUnionAggregation(pUnion, datasetsInOrder);
427 AggregationElement::processJoinNew()
430 processAnyScanElements();
432 BESDEBUG(
"ncml",
"AggregationElement: beginning joinNew on the following aggVars=" +
436 BESDEBUG(
"ncml",
"Merging dimensions from children into aggregated dataset..." << endl);
440 unsigned int newDimSize = _datasets.size();
444 if (_datasets.empty())
452 DDS* pTemplateDDS = _datasets[0]->getDDS();
453 NCML_ASSERT_MSG(pTemplateDDS,
"AggregationElement::processJoinNew(): NULL template dataset!");
456 AggregationUtil::unionAttrsInto( &(pAggDDS->get_attr_table()),
457 pTemplateDDS->get_attr_table() );
462 vector<string>::const_iterator endIt = _aggVars.end();
463 for (vector<string>::const_iterator it = _aggVars.begin(); it != endIt; ++it)
465 const string& varName = *it;
466 BESDEBUG(
"ncml",
"Aggregating with joinNew on variable=" << varName <<
"..." << endl);
467 processJoinNewOnAggVar(pAggDDS, varName, *pTemplateDDS);
475 AggregationUtil::resetCVInsertionPosition();
478 AggregationUtil::unionAllVariablesInto(pAggDDS, *pTemplateDDS,
true);
488 doAllScannersSpecifyNCoords(
const vector<ScanElement*>& scanners)
491 for (vector<ScanElement*>::const_iterator it = scanners.begin();
492 it != scanners.end();
496 if ((*it)->ncoords().empty())
507 AggregationElement::processJoinExisting()
509 BESDEBUG(
"ncml:2",
"Called AggregationElement::processJoinExisting()...");
512 processAnyScanElements();
515 if (_datasets.empty())
518 "In joinExisting aggregation we cannot have zero datasets specified!");
528 granuleList.reserve(_datasets.size());
529 fillDimensionCacheForJoinExistingDimension(granuleList, _dimName);
533 addNewDimensionForJoinExisting(granuleList);
538 BESDEBUG(
"ncml:2",
"Merging dimensions from children into aggregated dataset..." << endl);
539 mergeDimensions(
true, _dimName);
545 DDS* pTemplateDDS = _datasets[0]->getDDS();
546 NCML_ASSERT_MSG(pTemplateDDS,
"AggregationElement::processJoinExisting(): NULL template dataset!");
549 AggregationUtil::unionAttrsInto( &(pAggDDS->get_attr_table()),
550 pTemplateDDS->get_attr_table() );
553 decideWhichVariablesToJoinExist(*pTemplateDDS);
557 vector<string>::const_iterator endIt = _aggVars.end();
558 for (vector<string>::const_iterator it = _aggVars.begin(); it != endIt; ++it)
560 const string& varName = *it;
561 BESDEBUG(
"ncml",
"Aggregating with joinExisting on variable=" << varName <<
"..." << endl);
562 processJoinExistingOnAggVar(pAggDDS, varName, *pTemplateDDS);
568 unionAddAllRequiredNonAggregatedVariablesFrom(*pTemplateDDS);
572 AggregationElement::unionAddAllRequiredNonAggregatedVariablesFrom(
const DDS& templateDDS)
579 AggregationUtil::resetCVInsertionPosition();
587 AggregationUtil::unionAllVariablesInto(
getParentDataset()->getDDS(), templateDDS,
true);
598 AggregationUtil::unionAllVariablesInto(
getParentDataset()->getDDS(), templateDDS,
true);
603 AggregationElement::decideWhichVariablesToJoinExist(
const DDS& templateDDS)
606 if (_aggVars.empty())
608 BESDEBUG(
"ncml",
"Searching the the template DDS for variables with outer "
609 "dimension matching the join dimension = " << _dimName
610 <<
" in order to add them to the aggregation output list." << endl);
614 vector<string> matchingVars;
615 findVariablesWithOuterDimensionName(matchingVars, templateDDS, _dimName);
616 for (vector<string>::const_iterator it = matchingVars.begin();
617 it != matchingVars.end();
625 BESDEBUG(
"ncml",
"joinExist aggregation had variableAgg specified... "
626 "Validating these variables have outer dimension named "
630 for (vector<string>::const_iterator it = _aggVars.begin();
631 it != _aggVars.end();
634 BaseType* pVar = AggregationUtil::findVariableAtDDSTopLevel(templateDDS, *it);
639 std::ostringstream msg;
640 msg <<
"Error validating the variableAgg list. The variable named "
642 <<
" was not found in the top-level DDS!";
647 Array* pArray = AggregationUtil::getAsArrayIfPossible(pVar);
650 std::ostringstream msg;
651 msg <<
"The declared variableAgg aggregation variable named "
653 <<
" was not of a type able to be aggregated!";
658 if (pArray->dimension_name(pArray->dim_begin()) != _dimName)
660 std::ostringstream msg;
661 msg <<
"The declared variableAgg variable named "
663 <<
" did not match the outer dimension name "
665 <<
" for this joinExisting aggregation!";
670 std::ostringstream msg;
671 msg <<
"The variable named "
673 <<
" is a valid joinExisting variable. Will be added to output.";
674 BESDEBUG(
"ncml", msg.str() << endl);
681 AggregationElement::fillDimensionCacheForJoinExistingDimension(
688 vector<NetcdfElement*>::iterator endIt = _datasets.end();
689 for (vector<NetcdfElement*>::iterator it = _datasets.begin();
693 granuleList.push_back((*it)->getAggMemberDataset());
698 if (doesFirstGranuleSpecifyNcoords())
701 if (!doAllGranulesSpecifyNcoords())
704 "In a joinExisting aggregation we found that the first "
705 "granule specified an ncoords but not all of the others "
706 "did. Either all or none of them should have ncoords specified.");
711 seedDimensionCacheFromUserSpecs(granuleList);
718 if (doesDimensionCacheExist())
720 loadDimensionCacheFromCacheFile(granuleList);
727 seedDimensionCacheByQueryOfDatasets(granuleList);
733 AggregationElement::doesDimensionCacheExist()
const
736 BESDEBUG(
"ncml",
"Warning: joinExisting dimension cache"
737 " is not implemented and we'll force a slow load." << endl);
748 AggregationElement::doesFirstGranuleSpecifyNcoords()
const
750 if (_datasets.size() > 0)
752 return _datasets.at(0)->hasNcoords();
761 AggregationElement::doAllGranulesSpecifyNcoords()
const
764 vector<NetcdfElement*>::const_iterator endIt = _datasets.end();
765 for (vector<NetcdfElement*>::const_iterator it = _datasets.begin();
769 success = success && (*it)->hasNcoords();
779 AggregationElement::seedDimensionCacheFromUserSpecs(
agg_util::AMDList& rGranuleList)
const
781 NCML_ASSERT( _datasets.size() == rGranuleList.size() );
783 vector<NetcdfElement*>::const_iterator datasetIt;
784 AMDList::iterator amdIt;
785 for ( datasetIt = _datasets.begin(),
786 amdIt = rGranuleList.begin();
787 datasetIt != _datasets.end();
788 ++datasetIt, ++amdIt)
791 const NetcdfElement* pDataset = *datasetIt;
792 if (!pDataset->hasNcoords())
796 "Expected netcdf element member of a joinExisting "
797 "aggregation to have the ncoords attribute specified "
800 unsigned int ncoords = pDataset->getNcoordsAsUnsignedInt();
810 "Dimension cache bug");
817 AggregationElement::seedDimensionCacheByQueryOfDatasets(
agg_util::AMDList& rGranuleList)
const
820 "WARNING: netcdf@ncoords attribute not specified for the granules in joinExisting."
821 " We will query the granules serially for the dimensions size. NOTE: This is "
822 "potentially a very slow operation until cached!" << endl);
823 BESDEBUG(
"ncml",
"We will be loading " << rGranuleList.size() <<
" granules." << endl);
824 AMDList::iterator endIt = rGranuleList.end();
825 for (AMDList::iterator it = rGranuleList.begin();
830 "Getting joinExisting dimension for: " << (*it)->getLocation() <<
"..." << endl);
831 (*it)->fillDimensionCacheByUsingDataDDS();
832 BESDEBUG(
"ncml",
"... done." << endl);
838 AggregationElement::addNewDimensionForJoinExisting(
const agg_util::AMDList& rGranuleList)
841 unsigned int aggDimSize = 0;
842 for (AMDList::const_iterator it = rGranuleList.begin();
843 it != rGranuleList.end();
847 aggDimSize += (*it)->getCachedDimensionSize(_dimName);
853 "AggregationElement::addNewDimensionForJoinExisting() found a dimension "
854 "named " + _dimName +
" already but did not expect it!");
862 oss <<
"Added joinExisting aggregation dimension "
865 " with aggregated size= " <<
871 AggregationElement::findVariablesWithOuterDimensionName(
872 vector<string>& oMatchingVars,
873 const DDS& templateDDS,
874 const string& outerDimName)
const
876 for ( DDS::Vars_iter it = const_cast<DDS&>(templateDDS).var_begin();
877 it !=
const_cast<DDS&
>(templateDDS).var_end();
880 Array* pArray = AggregationUtil::getAsArrayIfPossible(*it);
882 if ( pArray && outerDimName == pArray->dimension_name(pArray->dim_begin()) )
884 oMatchingVars.push_back(pArray->name());
890 AggregationElement::getParamsForJoinAggOnVariable(
891 JoinAggParams* pOutParams,
893 const std::string& varName,
894 const DDS& templateDDS)
899 pOutParams->_pAggVarTemplate = AggregationUtil::getVariableNoRecurse(templateDDS, varName);
900 if (!(pOutParams->_pAggVarTemplate))
903 " We could not find a template for the specified aggregation variable="
905 +
" so we cannot continue the aggregation.");
911 "Didn't find a DimensionElement with the aggregation dimName=" + _dimName );
912 pOutParams->_pAggDim = &(pDim->getDimension());
922 BaseType* pExists = AggregationUtil::getVariableNoRecurse(aggOutputDDS, varName);
924 "Failed since the name of the new variable to add (name="
926 +
") already exists in the "
927 " output aggregation DDS! What happened?!");
932 collectAggMemberDatasets ( pOutParams->_memberDatasets );
936 AggregationElement::processJoinNewOnAggVar(
938 const std::string& varName,
939 const DDS& templateDDS)
942 JoinAggParams joinAggParams;
943 getParamsForJoinAggOnVariable(
950 BaseType* pAggVarTemplate = joinAggParams._pAggVarTemplate;
951 if (pAggVarTemplate->type() == dods_array_c)
953 processAggVarJoinNewForArray(*pAggDDS,
954 *(static_cast<Array*>(pAggVarTemplate)),
955 *(joinAggParams._pAggDim),
956 joinAggParams._memberDatasets );
958 else if (pAggVarTemplate->type() == dods_grid_c)
960 processAggVarJoinNewForGrid(*pAggDDS,
961 *(static_cast<Grid*>(pAggVarTemplate)),
962 *(joinAggParams._pAggDim),
963 joinAggParams._memberDatasets);
968 "Got an aggregation variable not of type Array or Grid, but of: " +
969 pAggVarTemplate->type_name() +
970 " which we cannot aggregate!");
977 AggregationElement::processJoinExistingOnAggVar(
979 const std::string& varName,
980 const DDS& templateDDS)
983 JoinAggParams joinAggParams;
984 getParamsForJoinAggOnVariable(
991 BaseType* pAggVarTemplate = joinAggParams._pAggVarTemplate;
992 if (pAggVarTemplate->type() == dods_array_c)
994 processAggVarJoinExistingForArray(*pAggDDS,
995 *(static_cast<Array*>(pAggVarTemplate)),
996 *(joinAggParams._pAggDim),
997 joinAggParams._memberDatasets );
999 else if (pAggVarTemplate->type() == dods_grid_c)
1001 processAggVarJoinExistingForGrid(*pAggDDS,
1002 *(static_cast<Grid*>(pAggVarTemplate)),
1003 *(joinAggParams._pAggDim),
1004 joinAggParams._memberDatasets);
1009 "Got an aggregation variable not of type Array or Grid, but of: " +
1010 pAggVarTemplate->type_name() +
" which we cannot aggregate!");
1016 AggregationElement::processAggVarJoinNewForArray(DDS& aggDDS,
1017 const libdap::Array& arrayTemplate,
1019 const AMDList& memberDatasets )
1022 auto_ptr<agg_util::ArrayGetterInterface>
1025 auto_ptr<ArrayAggregateOnOuterDimension> pAggArray(
1034 NCML_ASSERT_MSG(!(arrayGetter.get()),
"Expected auto_ptr owner xfer, failed!");
1040 "Adding new ArrayAggregateOnOuterDimension with name=" <<
1041 arrayTemplate.name() <<
1042 " to aggregated dataset!" <<
1045 aggDDS.add_var(pAggArray.get());
1050 AggregationElement::processAggVarJoinNewForGrid(DDS& aggDDS,
1051 const Grid& gridTemplate,
1053 const AMDList& memberDatasets )
1064 BESDEBUG(
"ncml",
"Adding new GridAggregateOnOuterDimension with name=" << gridTemplate.name() <<
1065 " to aggregated dataset!" << endl);
1066 aggDDS.add_var(pAggGrid.get());
1073 AggregationElement::processAggVarJoinExistingForArray(
1075 const libdap::Array& arrayTemplate,
1077 const AMDList& memberDatasets )
1080 auto_ptr<agg_util::ArrayGetterInterface> arrayGetter(
1083 auto_ptr<ArrayJoinExistingAggregation> pAggArray(
1092 NCML_ASSERT_MSG(!(arrayGetter.get()),
"Expected auto_ptr owner xfer, failed!");
1098 "Adding new ArrayJoinExistingAggregation with name=" <<
1099 arrayTemplate.name() <<
1100 " to aggregated dataset!" <<
1103 aggDDS.add_var(pAggArray.get());
1108 AggregationElement::processAggVarJoinExistingForGrid(
1110 const Grid& gridTemplate,
1112 const AMDList& memberDatasets)
1114 auto_ptr<GridJoinExistingAggregation> pAggGrid(
1122 "Adding new GridJoinExistingAggregation with name=" <<
1123 gridTemplate.name() <<
1124 " to aggregated dataset!" <<
1126 aggDDS.add_var(pAggGrid.get());
1130 AggregationElement::processParentDatasetCompleteForJoinNew()
1134 DDS* pParentDDS = pParentDataset->getDDS();
1138 NCML_ASSERT_MSG(pDim,
" AggregationElement::processParentDatasetCompleteForJoinNew(): "
1139 " didn't find a DimensionElement with the joinNew dimName=" + _dimName );
1143 BaseType* pBT = AggregationUtil::getVariableNoRecurse(*pParentDDS, dim.
name);
1149 pCV = createAndAddCoordinateVariableForNewDimension(*pParentDDS, dim);
1151 "failed to create a new coordinate variable for dim=" + dim.
name);
1157 VariableElement* pVarElt = pParentDataset->findVariableElementForLibdapVar(pBT);
1163 pCV = ensureVariableIsProperNewCoordinateVariable(pBT, dim,
true);
1168 pCV = processDeferredCoordinateVariable(pBT, dim);
1177 if (!_coordinateAxisType.empty())
1179 addCoordinateAxisType(*pCV, _coordinateAxisType);
1189 const string& aggVar = *it;
1190 BaseType* pBT = AggregationUtil::getVariableNoRecurse(*pParentDDS, aggVar);
1195 pGrid->prepend_map(pCV,
true);
1201 AggregationElement::processParentDatasetCompleteForJoinExisting()
1205 DDS* pAggDDS = pParentDataset->getDDS();
1210 " Didn't find a DimensionElement with the joinExisting dimName=" + _dimName );
1214 BaseType* pDimNameVar = AggregationUtil::getVariableNoRecurse(*pAggDDS, dim.
name);
1216 bool placeholderExists =
false;
1223 VariableElement* pVarElt = pParentDataset->findVariableElementForLibdapVar(pDimNameVar);
1229 pCV = ensureVariableIsProperNewCoordinateVariable(pDimNameVar, dim,
true);
1231 placeholderExists =
false;
1236 placeholderExists =
true;
1244 auto_ptr<ArrayJoinExistingAggregation> pNewMap(0);
1254 const string& aggVar = *it;
1255 BaseType* pAggVar = AggregationUtil::getVariableNoRecurse(*pAggDDS, aggVar);
1264 if ( !pCV || placeholderExists )
1273 if (placeholderExists)
1275 processPlaceholderCoordinateVariableForJoinExisting(*pDimNameVar,
1280 AggregationUtil::addOrReplaceVariableForName(pAggDDS, *(pNewMap.get()) );
1283 pCV = pNewMap.get();
1288 "Expected a coordinate variable since a Grid exists... what happened?");
1291 pGrid->prepend_map(pCV,
true);
1297 AggregationElement::processPlaceholderCoordinateVariableForJoinExisting(
1298 const libdap::BaseType& placeholderVar,
1299 libdap::Array* pNewVar)
1304 BaseType* pNewEltProto = pNewVar->var();
1306 if (placeholderVar.type() != pNewEltProto->type())
1309 " We expected the type of the placeholder coordinate variable to be the same "
1310 " as that created by the aggregation. Expected type="
1311 + pNewEltProto->type_name() +
1312 +
" but placeholder has type="
1313 + placeholderVar.type_name()
1314 +
" Please make sure these match in the input file!");
1318 AggregationUtil::gatherMetadataChangesFrom(pNewVar, placeholderVar);
1329 _coordinateAxisType = cat;
1335 return _coordinateAxisType;
1339 AggregationElement::ensureVariableIsProperNewCoordinateVariable(libdap::BaseType* pBT,
1341 bool throwOnInvalidCV)
const
1347 if (AggregationUtil::couldBeCoordinateVariable(pBT))
1350 Array* pArr =
static_cast<Array*
>(pBT);
1351 if ( pArr->length() ==
static_cast<int>(dim.
size) )
1359 oss << string(
"In the aggregation for dimension=") << dim.
name <<
1360 ": The coordinate variable we found does NOT have the same dimensionality as the"
1361 "aggregated dimension! We expected dimensionality=" << dim.
size <<
1362 " but the coordinate variable had dimensionality=" << pArr->length();
1363 BESDEBUG(
"ncml", oss.str() << endl);
1364 if (throwOnInvalidCV)
1373 std::ostringstream msg;
1374 msg <<
"Aggregation found a variable matching aggregated dimension name=" << dim.
name <<
1375 " but it was not a coordinate variable. "
1376 " It must be a 1D array whose dimension name is the same as its name. ";
1377 BESDEBUG(
"ncml",
"AggregationElement::ensureVariableIsProperNewCoordinateVariable: " +
1379 if (throwOnInvalidCV)
1390 AggregationElement::findMatchingCoordinateVariable(
1393 bool throwOnInvalidCV)
const
1395 BaseType* pBT = AggregationUtil::getVariableNoRecurse(dds, dim.
name);
1403 return ensureVariableIsProperNewCoordinateVariable(pBT, dim, throwOnInvalidCV);
1419 AggregationElement::processDeferredCoordinateVariable(libdap::BaseType* pBT,
const agg_util::Dimension& dim)
1423 BESDEBUG(
"ncml",
"Processing the placeholder coordinate variable (no values) for the "
1424 "current aggregation to add placeholder metadata to the generated values..." << endl);
1429 auto_ptr<Array> pNewArrCV = createCoordinateVariableForNewDimension(dim);
1431 " createCoordinateVariableForNewDimension()"
1435 BaseType* pNewEltProto = pNewArrCV->var();
1437 if (pBT->type() != pNewEltProto->type())
1440 " We expected the type of the placeholder coordinate variable to be the same "
1441 " as that created by the aggregation. Expected type="
1442 + pNewEltProto->type_name() +
1443 +
" but placeholder has type="
1445 +
" Please make sure these match in the input file!");
1453 pNewArrCV->get_attr_table() = pBT->get_attr_table();
1458 pDDS->del_var(pBT->name());
1462 BESDEBUG(
"ncml",
"Adding CV: " << pNewArrCV->name() << endl);
1463 pDDS->add_var(pNewArrCV.get());
1466 Array* pArrCV =
static_cast<Array*
>(AggregationUtil::getVariableNoRecurse(*pDDS, dim.
name));
1471 auto_ptr<libdap::Array>
1472 AggregationElement::createCoordinateVariableForNewDimension(
const agg_util::Dimension& dim)
const
1476 bool hasCoordValue = !(_datasets[0]->coordValue().empty());
1479 return createCoordinateVariableForNewDimensionUsingCoordValue(dim);
1483 return createCoordinateVariableForNewDimensionUsingLocation(dim);
1488 AggregationElement::createAndAddCoordinateVariableForNewDimension(DDS& dds,
const agg_util::Dimension& dim)
1490 auto_ptr<libdap::Array> pNewCV = createCoordinateVariableForNewDimension(dim);
1493 NCML_ASSERT_MSG(pNewCV.get(),
"AgregationElement::createCoordinateVariableForNewDimension() failed to create a coordinate variable!");
1501 BESDEBUG(
"ncml2",
"AggregationElement::createAndAddCoordinateVariableForNewDimension: " << pNewCV->name());
1503 dds.add_var(pNewCV.get());
1512 static int last_added = 0;
1513 DDS::Vars_iter pos = dds.var_begin();
1514 for (
int i = 0; i < last_added; ++i)
1517 dds.insert_var(pos, pNewCV.get());
1521 Array* pCV =
static_cast<Array*
>( AggregationUtil::getVariableNoRecurse(
1525 NCML_ASSERT_MSG(pCV,
"Logic Error: tried to add a new coordinate variable while processing joinNew"
1526 " but we couldn't locate it!");
1530 auto_ptr<libdap::Array>
1531 AggregationElement::createCoordinateVariableForNewDimensionUsingCoordValue(
const agg_util::Dimension& dim)
const
1534 NCML_ASSERT_MSG(_datasets.size() == dim.
size,
"Logic error: Number of datasets doesn't match dimension!");
1536 double doubleVal = 0;
1537 if (_datasets[0]->getCoordValueAsDouble(doubleVal))
1539 return createCoordinateVariableForNewDimensionUsingCoordValueAsDouble(dim);
1543 return createCoordinateVariableForNewDimensionUsingCoordValueAsString(dim);
1547 auto_ptr<libdap::Array>
1548 AggregationElement::createCoordinateVariableForNewDimensionUsingCoordValueAsDouble(
const agg_util::Dimension& dim)
const
1550 vector<dods_float64> coords;
1551 coords.reserve(dim.
size);
1552 double doubleVal = 0;
1554 for (
unsigned int i=0; i < _datasets.size(); ++i)
1556 const NetcdfElement* pDataset = _datasets[i];
1557 if (!pDataset->getCoordValueAsDouble(doubleVal))
1560 "In creating joinNew coordinate variable from coordValue, expected a coordValue of type double"
1561 " but failed! coordValue=" + pDataset->coordValue() +
1562 " which was in the dataset location=" + pDataset->location() +
1563 " with title=\"" + pDataset->title() +
"\"");
1567 coords.push_back(static_cast<dods_float64>(doubleVal));
1574 NCML_ASSERT_MSG(pNewCV.get(),
"createCoordinateVariableForNewDimensionUsingCoordValueAsDouble: failed to create"
1575 " the new Array<Float64> for variable: " + dim.
name);
1576 pNewCV->append_dim(dim.
size, dim.
name);
1577 pNewCV->set_value(coords, coords.size());
1581 auto_ptr<libdap::Array>
1582 AggregationElement::createCoordinateVariableForNewDimensionUsingCoordValueAsString(
const agg_util::Dimension& dim)
const
1585 vector<string> coords;
1586 coords.reserve(dim.
size);
1587 for (
unsigned int i=0; i < _datasets.size(); ++i)
1589 const NetcdfElement* pDataset = _datasets[i];
1590 if (pDataset->coordValue().empty())
1592 int parseLine =
line();
1594 "In creating joinNew coordinate variable from coordValue, expected a coordValue of type string"
1595 " but it was empty! dataset location=" + pDataset->location() +
1596 " with title=\"" + pDataset->title() +
"\"");
1600 coords.push_back(pDataset->coordValue());
1606 NCML_ASSERT_MSG(pNewCV.get(),
"createCoordinateVariableForNewDimensionUsingCoordValueAsString: failed to create"
1607 " the new Array<String> for variable: " + dim.
name);
1608 pNewCV->append_dim(dim.
size, dim.
name);
1609 pNewCV->set_value(coords, coords.size());
1613 auto_ptr<libdap::Array>
1614 AggregationElement::createCoordinateVariableForNewDimensionUsingLocation(
const agg_util::Dimension& dim)
const
1617 vector<string> coords;
1618 coords.reserve(dim.
size);
1619 for (
unsigned int i=0; i < _datasets.size(); ++i)
1621 const NetcdfElement* pDataset = _datasets[i];
1622 string location(
"");
1623 if (pDataset->location().empty())
1625 std::ostringstream oss;
1626 oss <<
"Virtual_Dataset_" << i;
1627 location = oss.str();
1631 location = pDataset->location();
1633 coords.push_back(location);
1638 NCML_ASSERT_MSG(pNewCV.get(),
"createCoordinateVariableForNewDimensionUsingCoordValueUsingLocation: failed to create"
1639 " the new Array<String> for variable: " + dim.
name);
1641 pNewCV->append_dim(dim.
size, dim.
name);
1642 pNewCV->set_value(coords, coords.size());
1647 AggregationElement::collectDatasetsInOrder(vector<const DDS*>& ddsList)
const
1650 ddsList.reserve(_datasets.size());
1651 vector<NetcdfElement*>::const_iterator endIt = _datasets.end();
1652 vector<NetcdfElement*>::const_iterator it;
1653 for (it = _datasets.begin(); it != endIt; ++it)
1655 const NetcdfElement* elt = *it;
1657 const DDS* pDDS = elt->getDDS();
1659 ddsList.push_back(pDDS);
1664 AggregationElement::collectAggMemberDatasets(
AMDList& rMemberDatasets)
const
1666 rMemberDatasets.resize(0);
1667 rMemberDatasets.reserve(_datasets.size());
1669 for (vector<NetcdfElement*>::const_iterator it = _datasets.begin();
1670 it != _datasets.end();
1678 if ( !( (*it)->ncoords().empty()) &&
1681 if (! (pAGM->isDimensionCached(_dimName)) )
1683 unsigned int ncoords = (*it)->getNcoordsAsUnsignedInt();
1690 rMemberDatasets.push_back( pAGM );
1695 AggregationElement::processAnyScanElements()
1697 if (_scanners.size() > 0)
1699 BESDEBUG(
"ncml",
"Started to process " << _scanners.size() <<
" scan elements..." << endl);
1702 vector<ScanElement*>::iterator it;
1703 vector<ScanElement*>::iterator endIt = _scanners.end();
1704 vector<NetcdfElement*> scannedDatasets;
1705 for (it = _scanners.begin(); it != endIt; ++it)
1707 BESDEBUG(
"ncml",
"Processing scan element = " << (*it)->toString() <<
" ..." << endl);
1711 (*it)->getDatasetList(scannedDatasets);
1716 vector<NetcdfElement*>::iterator datasetIt;
1717 vector<NetcdfElement*>::iterator datasetEndIt = scannedDatasets.end();
1718 for (datasetIt = scannedDatasets.begin();
1719 datasetIt != datasetEndIt;
1723 _parser->addChildDatasetToCurrentDataset(*datasetIt);
1725 (*datasetIt)->unref();
1728 scannedDatasets.clear();
1733 AggregationElement::mergeDimensions(
1734 bool checkDimensionMismatch,
1735 const std::string& dimToSkip)
1739 vector<NetcdfElement*>::const_iterator datasetsEndIt = _datasets.end();
1740 vector<NetcdfElement*>::const_iterator datasetsIt;
1741 for (datasetsIt = _datasets.begin(); datasetsIt != datasetsEndIt; ++datasetsIt)
1744 const NetcdfElement* dataset = *datasetsIt;
1746 const vector<DimensionElement*>& dimensions = dataset->getDimensionElements();
1747 vector<DimensionElement*>::const_iterator dimEndIt = dimensions.end();
1748 vector<DimensionElement*>::const_iterator dimIt;
1749 for (dimIt = dimensions.begin(); dimIt != dimEndIt; ++dimIt)
1751 const DimensionElement* pDim = *dimIt;
1754 if (!dimToSkip.empty() &&
1755 (pDim->name() == dimToSkip) )
1760 const DimensionElement* pUnionDim = pParent->getDimensionInLocalScope(pDim->name());
1764 if (!pUnionDim->checkDimensionsMatch(*pDim))
1766 string msg = string(
"The union aggregation already had a dimension=") +
1767 pUnionDim->toString() +
1768 " but we found another with different cardinality: " +
1770 " This is likely an error and could cause a later exception.";
1771 BESDEBUG(
"ncml",
"WARNING: " + msg);
1772 if (checkDimensionMismatch)
1775 msg +
" Scope=" +
_parser->getScopeString());
1782 BESDEBUG(
"ncml",
"Dimension name=" << pDim->name() <<
1783 " was not found in the union yet, so adding it. The full elt is: " <<
1784 pDim->toString() << endl);
1785 pParent->addDimension( const_cast<DimensionElement*>(pDim) );
1791 static const string COORDINATE_AXIS_TYPE_ATTR(
"_CoordinateAxisType");
1793 AggregationElement::addCoordinateAxisType(libdap::Array& rCV,
const std::string& cat)
1795 AttrTable& rAT = rCV.get_attr_table();
1796 AttrTable::Attr_iter foundIt = rAT.simple_find(COORDINATE_AXIS_TYPE_ATTR);
1798 if (foundIt != rAT.attr_end())
1800 rAT.del_attr(COORDINATE_AXIS_TYPE_ATTR);
1803 BESDEBUG(
"ncml3",
"Adding attribute to the aggregation variable " << rCV.name() <<
1804 " Attr is " << COORDINATE_AXIS_TYPE_ATTR <<
1809 rAT.append_attr(COORDINATE_AXIS_TYPE_ATTR,
"String", cat);
1813 AggregationElement::getValidAttributes()
1815 vector<string> attrs;
1816 attrs.push_back(
"type");
1817 attrs.push_back(
"dimName");
1818 attrs.push_back(
"recheckEvery");
virtual bool validateAttributes(const XMLAttributeMap &attrs, const vector< string > &validAttrs, vector< string > *pInvalidAttrs=0, bool printInvalid=true, bool throwOnError=true)
Check that the given attributes are all in the valid set, otherwise fill in *pInvalidAttrs with the p...
static std::auto_ptr< libdap::Array > makeArrayTemplateVariable(const string &type, const string &name, bool addTemplateVar)
Make an Array where T is the DAP simple type for the values in the Array.
Abstract helper superclass for allowing lazy access to the DataDDS for an aggregation.
virtual const string & getTypeName() const
Return the type of the element, which should be: the same as ConcreteClassName::getTypeName() ...
virtual string toString() const
Return a string describing the element.
bool isAggregationVariable(const string &name) const
AggVarIter endAggVarIter() const
virtual void handleContent(const string &content)
Handle the characters content for the element.
void setParentAggregation(AggregationElement *parent)
Set my parent AggregationElement to parent.
class ArrayAggregateOnOuterDimension
void addDimension(DimensionElement *dim)
Add the given element to this scope.
#define NCML_ASSERT(cond)
void setChildAggregation(AggregationElement *agg, bool throwIfExists=true)
Set our aggregation to the given agg.
virtual int unref() const
Decrease the reference count by one.
An abstract superclass for NCMLArray that handles the non-parameterized functionality and allows u...
void setVariableAggElement()
Should only be used by the VariableAggElement class to let us know it added the vars.
bool isUnionAggregation() const
virtual bool isDimensionCached(const std::string &dimName) const =0
Return whether the dimension is already cached, or would have to be loaded to be found.
virtual ~AggregationElement()
void addScanElement(ScanElement *pScanner)
Add a child ScanElement to the Aggregation to be used to to add to the list of child datasets...
const string getValueForLocalNameOrDefault(const string &localname, const string &defVal="") const
If there is an attribute with localname, return its value, else return default.
static bool isAllWhitespace(const std::string &str)
Is all the string whitespace as defined by chars in WHITESPACE ?
#define NCML_ASSERT_MSG(cond, msg)
Concrete class for NcML element.
Implementation of the element used to scan directories to create the set of files for an aggre...
virtual const libdap::DDS * getDDS() const
Return the DDS for this dataset, loading it in if needed.
const DimensionElement * getDimensionInLocalScope(const string &name) const
virtual NetcdfElement * clone() const
Make and return a copy of this.
virtual string toString() const
Return a string describing the element.
void setAggregationVariableCoordinateAxisType(const std::string &cat)
If a child scan contains a dateFormatMark, then we want to add a "_CoordinateAxisType" of "Time" By s...
bool isJoinExistingAggregation() const
virtual unsigned int getCachedDimensionSize(const std::string &dimName) const =0
Get the size of the given dimension named dimName cached within the dataset.
AggregationElement * getChildAggregation() const
Return the raw pointer (or NULL) to our contained aggregation.
A static class for encapsulating the aggregation functionality on libdap.
Concrete impl that simply finds the Array by looking for a variable of the given name at the top leve...
int getParseLineNumber() const
Get the line of the NCML file the parser is currently parsing.
static std::string printAttributeIfNotEmpty(const std::string &attrName, const std::string &attrValue)
Helper for subclasses implementing toString().
virtual void handleEnd()
Handle the closing of this element.
class GridAggregateOnOuterDimension : public GridAggregationBase
NetcdfElement * getParentDataset() const
#define THROW_NCML_PARSE_ERROR(parseLine, msg)
virtual int ref() const
Increase the reference count by one.
Struct for holding information about a dimension of data, minimally a name and a cardinality (size)...
AggVarIter beginAggVarIter() const
A reference to an RCObject which automatically ref() and deref() on creation and destruction.
virtual ScanElement * clone() const
Make and return a copy of this.
void setVariableGotValues(libdap::BaseType *pVarToValidate, bool removeEntry)
Lookup the VariableElement* associated with pVarToValidate via a previous addVariableToValidateOnClos...
vector< string >::const_iterator AggVarIter
static const string _sTypeName
Base class for NcML element concrete classes.
int line() const
Return the current parse line number.
bool gotVariableAggElement() const
whether this aggregation contained a variableAgg element to select aggregation variables.
void processParentDatasetComplete()
Called when the enclosing dataset is closing for the aggregation to handle any post processing that i...
#define THROW_NCML_INTERNAL_ERROR(msg)
void addChildDataset(NetcdfElement *pDataset)
Add a new dataset to the aggregation for the parse.
static const vector< string > _sValidAttrs
std::vector< RCPtr< AggMemberDataset > > AMDList
virtual void setAttributes(const XMLAttributeMap &attrs)
Set the attributes of this from the map.
void setParent(AggregationElement *pParent)
Set the parent of this element.
auto_ptr< ArrayJoinExistingAggregation > makeAggregatedOuterMapVector() const
Create a new map aggregated map vector for this aggregation, using its data templates, granule list, and outer dimension.
virtual void handleBegin()
Handle a begin on this element.
void addAggregationVariable(const string &name)
Set the variable with name as an aggregation variable for this aggregation.
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
NetcdfElement * setParentDataset(NetcdfElement *parent)
Set the parent and return the old one, which could be null.
bool isJoinNewAggregation() const
virtual void setDimensionCacheFor(const Dimension &dim, bool throwIfFound)=0
Seed the dimension cache using the given dimension, so that later calls to getDimensionSize for dim...
string printAggregationVariables() const
const std::string & getAggregationVariableCoordinateAxisType() const
Return the value set by setAggregationVariableCoordinateAxisType() or "" if none was set...
virtual AggregationElement * clone() const
Make and return a copy of this.