bes  Updated for version 3.20.6
NetcdfElement.cc
1 // This file is part of the "NcML Module" project, a BES module designed
3 // to allow NcML files to be used to be used as a wrapper to add
4 // AIS to existing datasets of any format.
5 //
6 // Copyright (c) 2009 OPeNDAP, Inc.
7 // Author: Michael Johnson <m.johnson@opendap.org>
8 //
9 // For more information, please also see the main website: http://opendap.org/
10 //
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Lesser General Public
13 // License as published by the Free Software Foundation; either
14 // version 2.1 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License along with this library; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 //
25 // Please see the files COPYING and COPYRIGHT for more information on the GLPL.
26 //
27 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
29 
30 #include "config.h"
31 
32 #include <BaseType.h> // libdap
33 #include <BESDapResponse.h> // bes
34 
35 #include "AggMemberDataset.h" // agg_util
36 #include "AggMemberDatasetDDSWrapper.h" // agg_util
37 #include "AggMemberDatasetSharedDDSWrapper.h" // agg_util
38 #include "AggMemberDatasetUsingLocationRef.h" // agg_util
39 #include "AggregationElement.h"
40 #include "DimensionElement.h"
41 #include "NetcdfElement.h"
42 #include "NCMLDebug.h"
43 #include "NCMLParser.h"
44 #include "NCMLUtil.h"
45 #include "VariableElement.h"
46 
47 #include <assert.h>
48 #include <sstream>
49 
50 using namespace std;
51 using libdap::DDS;
52 using namespace agg_util;
53 
54 namespace ncml_module {
55 
56 const string NetcdfElement::_sTypeName = "netcdf";
57 const vector<string> NetcdfElement::_sValidAttributes = getValidAttributes();
58 
59 NetcdfElement::NetcdfElement() :
60  NCMLElement(0), _location(""), _id(""), _title(""), _ncoords(""), _enhance(""), _addRecords(""), _coordValue(""), _fmrcDefinition(
61  ""), _gotMetadataDirective(false), _weOwnResponse(false), _loaded(false), _response(0), _aggregation(0), _parentAgg(
62  0), _dimensions(), _variableValidator(this)
63 {
64 }
65 
66 NetcdfElement::NetcdfElement(const NetcdfElement& proto) :
67  RCObjectInterface(), DDSAccessInterface(), DDSAccessRCInterface(), NCMLElement(proto), _location(proto._location), _id(
68  proto._id), _title(proto._title), _ncoords(proto._ncoords), _enhance(proto._enhance), _addRecords(
69  proto._addRecords), _coordValue(proto._coordValue), _fmrcDefinition(proto._fmrcDefinition), _gotMetadataDirective(
70  false), _weOwnResponse(false), _loaded(false), _response(0), _aggregation(0), _parentAgg(0) // we can't really set this to the proto one or we break an invariant...
71  , _dimensions(), _variableValidator(this) // start it empty rather than copy to avoid ref counting errors...
72 {
73  // we can't copy the proto response object... I'd say just don't allow this.
74  // if it's needed later, we can implement a proper full clone on a DDS, but the
75  // current one is buggy.
76  if (proto._response) {
77  THROW_NCML_INTERNAL_ERROR("Can't clone() a NetcdfElement that contains a response!");
78  }
79 
80  // Yuck clone the whole aggregation.
81  if (proto._aggregation.get()) {
82  setChildAggregation(proto._aggregation.get()->clone());
83  }
84 
85  // Deep copy the dimension table so they don't side effect each other...
86  vector<DimensionElement*>::const_iterator endIt = proto._dimensions.end();
87  vector<DimensionElement*>::const_iterator it;
88  for (it = proto._dimensions.begin(); it != endIt; ++it) {
89  DimensionElement* elt = *it;
90  addDimension(elt->clone());
91  }
92 }
93 
94 NetcdfElement::~NetcdfElement()
95 {
96  BESDEBUG("ncml:memory", "~NetcdfElement called...");
97  // Only if its ours do we nuke it.
98  if (_weOwnResponse) {
99  SAFE_DELETE(_response);
100  }
101  _response = 0; // but null it in all cases.
102  _parentAgg = 0;
103  clearDimensions();
104 
105  // _aggregation dtor will take care of the ref itself.
106 }
107 
108 const string&
109 NetcdfElement::getTypeName() const
110 {
111  return _sTypeName;
112 }
113 
115 NetcdfElement::clone() const
116 {
117  return new NetcdfElement(*this);
118 }
119 
120 void NetcdfElement::setAttributes(const XMLAttributeMap& attrs)
121 {
122  // Make sure they exist in the schema, even if we don't support them.
123  validateAttributes(attrs, _sValidAttributes);
124 
125  // set them
126  _location = attrs.getValueForLocalNameOrDefault("location");
127  _id = attrs.getValueForLocalNameOrDefault("id");
128  _title = attrs.getValueForLocalNameOrDefault("title");
129  _enhance = attrs.getValueForLocalNameOrDefault("enhance");
130  _addRecords = attrs.getValueForLocalNameOrDefault("addRecords");
131  // Aggregation children only below!
132  _ncoords = attrs.getValueForLocalNameOrDefault("ncoords");
133  _coordValue = attrs.getValueForLocalNameOrDefault("coordValue");
134  _fmrcDefinition = attrs.getValueForLocalNameOrDefault("fmrcDefinition");
135 
136  throwOnUnsupportedAttributes();
137 }
138 
139 void NetcdfElement::handleBegin()
140 {
141  BESDEBUG("ncml", "NetcdfElement::handleBegin on " << toString() << endl);
142  NCMLParser& p = *_parser;
143 
144  // Make sure that we are in an AggregationElement if we're not root!
145  if (p.getRootDataset() && !p.isScopeAggregation()) {
146  THROW_NCML_PARSE_ERROR(_parser->getParseLineNumber(),
147  "Got a nested <netcdf> element which was NOT a direct child of an <aggregation>!");
148  }
149 
150  // Tell the parser we got a new current dataset.
151  // If this is the root, it also needs to set up our response!!
152  p.pushCurrentDataset(this);
153 
154  // Make sure the attributes that are set are valid for context
155  // that we just pushed.
156  validateAttributeContextOrThrow();
157 }
158 
159 void NetcdfElement::handleContent(const string& content)
160 {
161  if (!NCMLUtil::isAllWhitespace(content)) {
162  THROW_NCML_PARSE_ERROR(_parser->getParseLineNumber(),
163  "Got non-whitespace for element content and didn't expect it. Element=" + toString() + " content=\""
164  + content + "\"");
165  }
166 }
167 
168 void NetcdfElement::handleEnd()
169 {
170  BESDEBUG("ncml", "NetcdfElement::handleEnd called!" << endl);
171 
172  if (!_parser->isScopeNetcdf()) {
173  THROW_NCML_PARSE_ERROR(_parser->getParseLineNumber(), "Got close of <netcdf> node while not within one!");
174  }
175 
176  // If we had an aggregation, we must tell it to finish any post-processing that
177  // it needs to do to make the aggregations correct (like add Grid map vectors
178  // for new dimensions)
179  if (_aggregation.get()) {
180  _aggregation->processParentDatasetComplete();
181  }
182 
183  // At this point, any deferred new variables MUST have their values set
184  // to preserve an invariant (and avoid cryptic internal error in libdap).
185  // So validate any deferred new variables now:
186  _variableValidator.validate(); // throws parse error if failure....
187 
188  // Tell the parser to close the current dataset and figure out what the new current one is!
189  // We pass our ptr to make sure that we're the current one to avoid logic bugs!!
190  _parser->popCurrentDataset(this);
191 
192  // We'll leave our element table around until we're destroyed since people are allowed to use it if they
193  // maintained a ref to us....
194 }
195 
196 string NetcdfElement::toString() const
197 {
198  return "<" + _sTypeName + " " + "location=\"" + _location + "\""
199  + // always print this one even in empty.
200  printAttributeIfNotEmpty("id", _id) + printAttributeIfNotEmpty("title", _title)
201  + printAttributeIfNotEmpty("enhance", _enhance) + printAttributeIfNotEmpty("addRecords", _addRecords)
202  + printAttributeIfNotEmpty("ncoords", _ncoords) + printAttributeIfNotEmpty("coordValue", _coordValue)
203  + printAttributeIfNotEmpty("fmrcDefinition", _fmrcDefinition) + ">";
204 }
205 
206 const libdap::DDS*
207 NetcdfElement::getDDS() const
208 {
209  return const_cast<NetcdfElement*>(this)->getDDS();
210 }
211 
212 libdap::DDS*
213 NetcdfElement::getDDS()
214 {
215  // lazy eval loading the dds
216  if (!_loaded) {
217  BESDEBUG("ncml", "Lazy loading DDX for location=" << location() << endl);
218  loadLocation();
219  }
220 
221  if (_response) {
222  return NCMLUtil::getDDSFromEitherResponse(_response);
223  }
224  else {
225  return 0;
226  }
227 }
228 
229 bool NetcdfElement::isValid() const
230 {
231  // Right now we need these ptrs valid to be ready...
232  // Technically handleBegin() sets the parser,
233  // so we're not ready until after that has successfully completed.
234  return _response && _parser;
235 }
236 
237 unsigned int NetcdfElement::getNcoordsAsUnsignedInt() const
238 {
239  NCML_ASSERT_MSG(hasNcoords(),
240  "NetcdfElement::getNCoords(): called illegally when no ncoords attribute was specified!");
241  unsigned int num = 0;
242  if (!NCMLUtil::toUnsignedInt(_ncoords, num)) {
243  THROW_NCML_PARSE_ERROR(line(), "A <netcdf> element has an invalid ncoords attribute set. Bad value was:"
244  "\"" + _ncoords + "\"");
245  }
246  return num;
247 }
248 
249 void NetcdfElement::borrowResponseObject(BESDapResponse* pResponse)
250 {
251  NCML_ASSERT_MSG(!_response, "_response object should be NULL for proper logic of borrowResponseObject call!");
252  _response = pResponse;
253  _weOwnResponse = false;
254 }
255 
256 void NetcdfElement::unborrowResponseObject(BESDapResponse* pResponse)
257 {
258  NCML_ASSERT_MSG(pResponse == _response,
259  "NetcdfElement::unborrowResponseObject() called with a response we are not borrowing.");
260  _response = 0;
261 }
262 
263 void NetcdfElement::createResponseObject(DDSLoader::ResponseType type)
264 {
265  if (_response) {
266  THROW_NCML_INTERNAL_ERROR(
267  "NetcdfElement::createResponseObject(): Called when we already had a _response! Logic error!");
268  }
269 
270  VALID_PTR(_parser);
271 
272  // Make a new response and store the raw ptr, noting that we need to delete it in dtor.
273  std::auto_ptr<BESDapResponse> newResponse = _parser->getDDSLoader().makeResponseForType(type);
274  VALID_PTR(newResponse.get());
275  _response = newResponse.release();
276  _weOwnResponse = true;
277 }
278 
279 RCPtr<agg_util::AggMemberDataset> NetcdfElement::getAggMemberDataset() const
280 {
281  // If not created yet, make a new
282  // one in an RCPtr, store a weak ref,
283  // and return it.
284  RCPtr<AggMemberDataset> pAGM(0);
285  if (_pDatasetWrapper.empty()) {
286  if (_location.empty()) {
287  // if the location is empty, we must assume we have a valid DDS
288  // that has been created virtually or as a nested aggregation
289  // We create a wrapper for the NetcdfElement in this case
290  // using the ref-counted DDS accessor interface.
291  const DDSAccessRCInterface* pDDSHolder = this;
293  }
294  else {
295  pAGM = new AggMemberDatasetUsingLocationRef(_location, _parser->getDDSLoader());
296  }
297 
298  VALID_PTR(pAGM.get());
299 
300  // Make a weak ref to it, semantically const
301  const_cast<NetcdfElement*>(this)->_pDatasetWrapper = WeakRCPtr<AggMemberDataset>(pAGM.get());
302  }
303 
304  // Either way the weak ref is valid here, so return a new RCPtr to it
305  NCML_ASSERT(!_pDatasetWrapper.empty());
306  return _pDatasetWrapper.lock();
307 }
308 
309 const DimensionElement*
310 NetcdfElement::getDimensionInLocalScope(const string& name) const
311 {
312  const DimensionElement* ret = 0;
313  vector<DimensionElement*>::const_iterator endIt = _dimensions.end();
314  for (vector<DimensionElement*>::const_iterator it = _dimensions.begin(); it != endIt; ++it) {
315  const DimensionElement* pElt = *it;
316  VALID_PTR(pElt);
317  if (pElt->name() == name) {
318  ret = pElt;
319  break;
320  }
321  }
322  return ret;
323 }
324 
325 const DimensionElement*
326 NetcdfElement::getDimensionInFullScope(const string& name) const
327 {
328  // Base case...
329  const DimensionElement* elt = 0;
330  elt = getDimensionInLocalScope(name);
331  if (!elt) {
332  NetcdfElement* parentDataset = getParentDataset();
333  if (parentDataset) {
334  elt = parentDataset->getDimensionInFullScope(name);
335  }
336  }
337  return elt;
338 }
339 
340 void NetcdfElement::addDimension(DimensionElement* dim)
341 {
342  VALID_PTR(dim);
343  if (getDimensionInLocalScope(dim->name())) {
344  THROW_NCML_INTERNAL_ERROR(
345  "NCMLParser::addDimension(): already found dimension with name while adding " + dim->toString());
346  }
347 
348  _dimensions.push_back(dim);
349  dim->ref(); // strong reference!
350 
351  BESDEBUG("ncml", "Added dimension to dataset. Dimension Table is now: " << printDimensions() << endl);
352 }
353 
354 string NetcdfElement::printDimensions() const
355 {
356  string ret = "Dimensions = {\n";
357  vector<DimensionElement*>::const_iterator endIt = _dimensions.end();
358  vector<DimensionElement*>::const_iterator it;
359  for (it = _dimensions.begin(); it != endIt; ++it) {
360  ret += (*it)->toString() + "\n";
361  }
362  ret += "}";
363  return ret;
364 }
365 
366 void NetcdfElement::clearDimensions()
367 {
368  while (!_dimensions.empty()) {
369  DimensionElement* elt = _dimensions.back();
370  elt->unref();
371  _dimensions.pop_back();
372  }
373  _dimensions.resize(0);
374 }
375 
376 const std::vector<DimensionElement*>&
377 NetcdfElement::getDimensionElements() const
378 {
379  return _dimensions;
380 }
381 
382 void NetcdfElement::setChildAggregation(AggregationElement* agg, bool throwIfExists/*=true*/)
383 {
384  if (_aggregation.get() && throwIfExists) {
385  THROW_NCML_INTERNAL_ERROR(
386  "NetcdfElement::setAggregation: We were called but we already contain a non-NULL aggregation! Previous="
387  + _aggregation->toString() + " and the new one is: " + agg->toString());
388  }
389 
390  // Otherwise, we can just set it and rely on the smart pointer to do the right thing
391  _aggregation = agg; // this will implicitly convert the raw ptr to a smart ptr
392 
393  // Also set a weak reference to this as the parent of the aggregation for walking up the tree...
394  _aggregation->setParentDataset(this);
395 }
396 
398 NetcdfElement::getParentDataset() const
399 {
400  NetcdfElement* ret = 0;
401  if (_parentAgg && _parentAgg->getParentDataset()) {
402  ret = _parentAgg->getParentDataset();
403  }
404  return ret;
405 }
406 
408 NetcdfElement::getParentAggregation() const
409 {
410  return _parentAgg;
411 }
412 
413 void NetcdfElement::setParentAggregation(AggregationElement* parent)
414 {
415  _parentAgg = parent;
416 }
417 
419 NetcdfElement::getChildAggregation() const
420 {
421  return _aggregation.get();
422 }
423 
424 #if 0 // not sure we need this yet...
425 template <typename T>
426 int
427 NetcdfElement::getCoordValueVector(vector<T>& values) const
428 {
429  // clear it out just in case.
430  values.resize(0);
431 
432  // first, tokenize into strings
433  vector<string> tokens;
434  int numToks = NCMLUtil::tokenize(_coordValue, tokens, NCMLUtil::WHITESPACE);
435  values.reserve(numToks);
436 
437  for (int i=0; i<numToks; ++i)
438  {
439  stringstream iss(tokens[i]);
440  T val;
441  iss >> val;
442  if (iss.fail())
443  {
444  THROW_NCML_PARSE_ERROR(_parser->getParseLineNumber(),
445  "NetcdfElement::getCoordValueVector(): "
446  "Could not parse the token \"" + tokens[i] + "\""
447  " into the required data type.");
448  }
449  else
450  {
451  values.push_back(val);
452  }
453  }
454 }
455 #endif
456 
457 bool NetcdfElement::getCoordValueAsDouble(double& val) const
458 {
459  if (_coordValue.empty()) {
460  return false;
461  }
462 
463  std::istringstream iss(_coordValue);
464  double num;
465  iss >> num;
466  // eof() to make sure we parsed it all. >> can stop early on malformedness.
467  if (iss.fail() || !iss.eof()) {
468  return false;
469  }
470  else {
471  val = num;
472  return true;
473  }
474 }
475 
476 void NetcdfElement::addVariableToValidateOnClose(libdap::BaseType* pNewVar, VariableElement* pVE)
477 {
478  _variableValidator.addVariableToValidate(pNewVar, pVE);
479 }
480 
481 void NetcdfElement::setVariableGotValues(libdap::BaseType* pVarToValidate, bool removeEntry)
482 {
483  _variableValidator.setVariableGotValues(pVarToValidate);
484  if (removeEntry) {
485  _variableValidator.removeVariableToValidate(pVarToValidate);
486  }
487 }
488 
489 /********** Class Methods ***********/
490 
491 bool NetcdfElement::isLocationLexicographicallyLessThan(const NetcdfElement* pLHS, const NetcdfElement* pRHS)
492 {
493  // args should never be null, but let's catch the error in dev if we goof.
494  // I don't want to use VALID_PTR here to avoid exception overhead in an internal
495  // sort function.
496  assert(pLHS);
497  assert(pRHS);
498  return (pLHS->location().compare(pRHS->location()) < 0);
499 }
500 
501 bool NetcdfElement::isCoordValueLexicographicallyLessThan(const NetcdfElement* pLHS, const NetcdfElement* pRHS)
502 {
503  // args should never be null, but let's catch the error in dev if we goof.
504  // I don't want to use VALID_PTR here to avoid exception overhead in an internal
505  // sort function.
506  assert(pLHS);
507  assert(pRHS);
508  return (pLHS->coordValue().compare(pRHS->coordValue()) < 0);
509 }
510 
513 
514 void NetcdfElement::loadLocation()
515 {
516  if (_location.empty()) {
517  // nothing to load, so we're loaded I guess.
518  _loaded = true;
519  return;
520  }
521 
522  // We better have one! This gets created up front now. It will be an empty DDS
523  NCML_ASSERT_MSG(_response,
524  "NetcdfElement::loadLocation(): Requires a valid _response via borrowResponseObject() or createResponseObject() prior to call!");
525 
526  // Use the loader to load the location
527  // If not found, this call will throw an exception and we'll just unwind out.
528  if (_parser) {
529  _parser->loadLocation(_location, _parser->_responseType, _response);
530  _loaded = true;
531  }
532 }
533 
534 void NetcdfElement::throwOnUnsupportedAttributes()
535 {
536  const string msgStart = "NetcdfElement: unsupported attribute: ";
537  const string msgEnd = " was declared.";
538  if (!_enhance.empty()) {
539  THROW_NCML_PARSE_ERROR(_parser->getParseLineNumber(), msgStart + "enhance" + msgEnd);
540  }
541  if (!_addRecords.empty()) {
542  THROW_NCML_PARSE_ERROR(_parser->getParseLineNumber(), msgStart + "addRecords" + msgEnd);
543  }
544 
545  // not until fmrc
546  if (!_fmrcDefinition.empty()) {
547  THROW_NCML_PARSE_ERROR(_parser->getParseLineNumber(), msgStart + "fmrcDefinition" + msgEnd);
548  }
549 }
550 
551 bool NetcdfElement::validateAttributeContextOrThrow() const
552 {
553  if (hasNcoords()) {
554  AggregationElement* pParentAgg = getParentAggregation();
555  if (!pParentAgg || !(pParentAgg->isJoinExistingAggregation())) {
556  THROW_NCML_PARSE_ERROR(line(), "Cannot specify netcdf@ncoords attribute while not within a "
557  "joinExisting aggregation!");
558  }
559  }
560  return true;
561 }
562 
563 vector<string> NetcdfElement::getValidAttributes()
564 {
565  vector<string> validAttrs;
566  validAttrs.push_back("schemaLocation");
567  validAttrs.push_back("location");
568  validAttrs.push_back("id");
569  validAttrs.push_back("title");
570  validAttrs.push_back("enhance");
571  validAttrs.push_back("addRecords");
572  // following only valid inside aggregation, will need to test for that later.
573  validAttrs.push_back("ncoords");
574  validAttrs.push_back("coordValue");
575  validAttrs.push_back("fmrcDefinition");
576 
577  return validAttrs;
578 }
579 
580 /******************** Inner Class Def of VariableValueValidator *********************/
581 
582 typedef vector<NetcdfElement::VariableValueValidator::VVVEntry> VVVEntries;
583 
584 NetcdfElement::VariableValueValidator::VariableValueValidator(NetcdfElement* pParent) :
585  _entries(), _pParent(pParent)
586 {
587 }
588 
590 {
591  // For each entry, deref the VariableElement and clear it out.
592  VVVEntries::iterator it;
593  VVVEntries::iterator endIt = _entries.end();
594  for (it = _entries.begin(); it != endIt; ++it) {
595  VVVEntry& entry = *it;
596  entry._pVarElt->unref();
597  entry.clear();
598  }
599  _entries.resize(0);
600 }
601 
603 {
604  VALID_PTR(pNewVar);
605  VALID_PTR(pVE);
606  {
607  VVVEntry* pExisting = findEntryByLibdapVar(pNewVar);
608  NCML_ASSERT_MSG(!pExisting,
609  "NetcdfElement::VariableValueValidator::addVariableToValidate: var was already added!");
610  }
611 
612  // Up the ref count to keep it around and add an entry for it
613  pVE->ref();
614  _entries.push_back(VVVEntry(pNewVar, pVE));
615 }
616 
618 {
619  for (unsigned int i = 0; i < _entries.size(); ++i) {
620  if (_entries[i]._pNewVar == pVarToRemove) {
621  _entries[i]._pVarElt->unref();
622  _entries[i] = _entries[_entries.size() - 1];
623  _entries.pop_back();
624  break;
625  }
626  }
627 }
628 
630 {
631  VALID_PTR(pVarToValidate);
632  VVVEntry* pEntry = findEntryByLibdapVar(pVarToValidate);
633  NCML_ASSERT_MSG(pEntry,
634  "NetcdfElement::VariableValueValidator::setVariableGotValues: expected to find the var name="
635  + pVarToValidate->name() + " but we did not!");
636  pEntry->_pVarElt->setGotValues();
637 }
638 
641 {
642  return _variableValidator.findVariableElementForLibdapVar(pNewVar);
643 }
644 
646 {
647  VVVEntries::iterator it;
648  VVVEntries::iterator endIt = _entries.end();
649  for (it = _entries.begin(); it != endIt; ++it) {
650  VVVEntry& entry = *it;
651  // If the values was never set...
652  if (!entry._pVarElt->checkGotValues()) {
653  THROW_NCML_PARSE_ERROR(_pParent->line(),
654  "On closing the <netcdf> element, we found a new variable name=" + entry._pNewVar->name()
655  + " that was added"
656  " to the dataset but which never had values set on it. This is illegal!"
657  " Please make sure all variables in this dataset have values set on them"
658  " or that they are new coordinate variables for a joinNew aggregation.");
659  }
660  }
661  return true;
662 }
663 
665 NetcdfElement::VariableValueValidator::findEntryByLibdapVar(libdap::BaseType* pVarToFind)
666 {
667  VALID_PTR(pVarToFind);
668  VVVEntry* pRetVal = 0;
669  VVVEntries::iterator it;
670  VVVEntries::iterator endIt = _entries.end();
671  for (it = _entries.begin(); it != endIt; ++it) {
672  VVVEntry& entry = *it;
673  if (entry._pNewVar == pVarToFind) {
674  pRetVal = &entry;
675  break;
676  }
677  }
678  return pRetVal;
679 }
680 
681 VariableElement*
683 {
684  VALID_PTR(pVarToFind);
685  VVVEntry* pRetVal = findEntryByLibdapVar(pVarToFind);
686  if (pRetVal) {
687  return pRetVal->_pVarElt;
688  }
689  else {
690  return 0;
691  }
692 }
693 
694 } // namespace ncml_module
agg_util::RCObject::unref
virtual int unref() const
Definition: RCObject.cc:76
ncml_module::NetcdfElement::VariableValueValidator::removeVariableToValidate
void removeVariableToValidate(libdap::BaseType *pVarToRemove)
Definition: NetcdfElement.cc:617
ncml_module::NetcdfElement::VariableValueValidator::setVariableGotValues
void setVariableGotValues(libdap::BaseType *pVarToValidate)
Definition: NetcdfElement.cc:629
agg_util::AggMemberDatasetUsingLocationRef
Definition: AggMemberDatasetUsingLocationRef.h:60
ncml_module::DimensionElement::toString
virtual std::string toString() const
Definition: DimensionElement.cc:170
BESDapResponse
Represents an OPeNDAP DAP response object within the BES.
Definition: BESDapResponse.h:41
ncml_module::AggregationElement::setParentDataset
NetcdfElement * setParentDataset(NetcdfElement *parent)
Private Impl.
Definition: AggregationElement.cc:350
ncml_module::NetcdfElement
Concrete class for NcML <netcdf> element.
Definition: NetcdfElement.h:62
ncml_module::VariableElement::setGotValues
void setGotValues()
Definition: VariableElement.cc:146
ncml_module::NetcdfElement::VariableValueValidator::VVVEntry
Definition: NetcdfElement.h:468
agg_util::DDSAccessRCInterface
Definition: DDSAccessInterface.h:62
ncml_module::NCMLParser
Definition: NCMLParser.h:158
ncml_module::NetcdfElement::VariableValueValidator::~VariableValueValidator
~VariableValueValidator()
Definition: NetcdfElement.cc:589
agg_util::WeakRCPtr
Definition: RCObject.h:412
ncml_module::XMLAttributeMap
Definition: XMLHelpers.h:93
agg_util
Helper class for temporarily hijacking an existing dhi to load a DDX response for one particular file...
Definition: AggMemberDataset.cc:38
ncml_module::VariableElement::checkGotValues
bool checkGotValues() const
Definition: VariableElement.cc:141
ncml_module::NetcdfElement::getDimensionInFullScope
const DimensionElement * getDimensionInFullScope(const std::string &name) const
Definition: NetcdfElement.cc:326
ncml_module::DimensionElement
Definition: DimensionElement.h:55
ncml_module::NetcdfElement::getParentDataset
NetcdfElement * getParentDataset() const
Definition: NetcdfElement.cc:398
ncml_module::VariableElement
Concrete class for NcML <variable> element.
Definition: VariableElement.h:58
agg_util::DDSLoader::ResponseType
ResponseType
Definition: DDSLoader.h:94
ncml_module::AggregationElement
Definition: AggregationElement.h:61
agg_util::AggMemberDatasetSharedDDSWrapper
Definition: AggMemberDatasetSharedDDSWrapper.h:54
ncml_module::NetcdfElement::VariableValueValidator::addVariableToValidate
void addVariableToValidate(libdap::BaseType *pNewVar, VariableElement *pVE)
Definition: NetcdfElement.cc:602
ncml_module::NetcdfElement::VariableValueValidator::validate
bool validate()
Definition: NetcdfElement.cc:645
agg_util::DDSAccessInterface
Definition: DDSAccessInterface.h:45
agg_util::RCObjectInterface
Definition: RCObjectInterface.h:39
ncml_module
NcML Parser for adding/modifying/removing metadata (attributes) to existing local datasets using NcML...
Definition: AggregationElement.cc:72
ncml_module::NetcdfElement::findVariableElementForLibdapVar
VariableElement * findVariableElementForLibdapVar(libdap::BaseType *pNewVar)
Definition: NetcdfElement.cc:640
agg_util::RCObject::ref
virtual int ref() const
Definition: RCObject.cc:69
ncml_module::XMLAttributeMap::getValueForLocalNameOrDefault
const std::string getValueForLocalNameOrDefault(const std::string &localname, const std::string &defVal="") const
Definition: XMLHelpers.cc:181
agg_util::RCPtr
A reference to an RCObject which automatically ref() and deref() on creation and destruction.
Definition: RCObject.h:284
ncml_module::NetcdfElement::VariableValueValidator::findVariableElementForLibdapVar
VariableElement * findVariableElementForLibdapVar(libdap::BaseType *pNewVar)
Definition: NetcdfElement.cc:682
ncml_module::AggregationElement::toString
virtual string toString() const
Definition: AggregationElement.cc:233