OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
NetcdfElement.cc
Go to the documentation of this file.
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 
36 #include "AggMemberDataset.h" // agg_util
37 #include "AggMemberDatasetDDSWrapper.h" // agg_util
38 #include "AggMemberDatasetSharedDDSWrapper.h" // agg_util
39 #include "AggMemberDatasetUsingLocationRef.h" // agg_util
40 #include "AggregationElement.h"
41 #include "DimensionElement.h"
42 #include "NetcdfElement.h"
43 #include "NCMLDebug.h"
44 #include "NCMLParser.h"
45 #include "NCMLUtil.h"
46 #include "VariableElement.h"
47 
48 #include <assert.h>
49 #include <sstream>
50 
51 using namespace std;
52 using libdap::DDS;
53 using namespace agg_util;
54 
55 namespace ncml_module
56 {
57 
58  const string NetcdfElement::_sTypeName = "netcdf";
59  const vector<string> NetcdfElement::_sValidAttributes = getValidAttributes();
60 
61  NetcdfElement::NetcdfElement()
62  : NCMLElement(0)
63  , _location("")
64  , _id("")
65  , _title("")
66  , _ncoords("")
67  , _enhance("")
68  , _addRecords("")
69  , _coordValue("")
70  , _fmrcDefinition("")
71  , _gotMetadataDirective(false)
72  , _weOwnResponse(false)
73  , _loaded(false)
74  , _response(0)
75  , _aggregation(0)
76  , _parentAgg(0)
77  , _dimensions()
78  , _variableValidator(this)
79  {
80  }
81 
86  , NCMLElement(proto)
87  , _location(proto._location)
88  , _id(proto._id)
89  , _title(proto._title)
90  , _ncoords(proto._ncoords)
91  , _enhance(proto._enhance)
92  , _addRecords(proto._addRecords)
93  , _coordValue(proto._coordValue)
94  , _fmrcDefinition(proto._fmrcDefinition)
95  , _gotMetadataDirective(false)
96  , _weOwnResponse(false)
97  , _loaded(false)
98  , _response(0)
99  , _aggregation(0)
100  , _parentAgg(0) // we can't really set this to the proto one or we break an invariant...
101  , _dimensions()
102  , _variableValidator(this) // start it empty rather than copy to avoid ref counting errors...
103  {
104  // we can't copy the proto response object... I'd say just don't allow this.
105  // if it's needed later, we can implement a proper full clone on a DDS, but the
106  // current one is buggy.
107  if (proto._response)
108  {
109  THROW_NCML_INTERNAL_ERROR("Can't clone() a NetcdfElement that contains a response!");
110  }
111 
112  // Yuck clone the whole aggregation.
113  if (proto._aggregation.get())
114  {
115  setChildAggregation( proto._aggregation.get()->clone() );
116  }
117 
118  // Deep copy the dimension table so they don't side effect each other...
119  vector<DimensionElement*>::const_iterator endIt = proto._dimensions.end();
120  vector<DimensionElement*>::const_iterator it;
121  for (it = proto._dimensions.begin(); it != endIt; ++it)
122  {
123  DimensionElement* elt = *it;
124  addDimension(elt->clone());
125  }
126  }
127 
129  {
130  BESDEBUG("ncml:memory", "~NetcdfElement called...");
131  // Only if its ours do we nuke it.
132  if (_weOwnResponse)
133  {
134  SAFE_DELETE(_response);
135  }
136  _response = 0; // but null it in all cases.
137  _parentAgg = 0;
138  clearDimensions();
139 
140  // _aggregation dtor will take care of the ref itself.
141  }
142 
143  const string&
145  {
146  return _sTypeName;
147  }
148 
151  {
152  return new NetcdfElement(*this);
153  }
154 
155  void
157  {
158  // Make sure they exist in the schema, even if we don't support them.
160 
161  // set them
162  _location = attrs.getValueForLocalNameOrDefault("location");
163  _id = attrs.getValueForLocalNameOrDefault("id");
164  _title = attrs.getValueForLocalNameOrDefault("title");
165  _enhance = attrs.getValueForLocalNameOrDefault("enhance");
166  _addRecords = attrs.getValueForLocalNameOrDefault("addRecords");
167  // Aggregation children only below!
168  _ncoords = attrs.getValueForLocalNameOrDefault("ncoords");
169  _coordValue = attrs.getValueForLocalNameOrDefault("coordValue");
170  _fmrcDefinition = attrs.getValueForLocalNameOrDefault("fmrcDefinition");
171 
172  throwOnUnsupportedAttributes();
173  }
174 
175  void
177  {
178  BESDEBUG("ncml", "NetcdfElement::handleBegin on " << toString() << endl);
179  NCMLParser& p = *_parser;
180 
181  // Make sure that we are in an AggregationElement if we're not root!
182  if (p.getRootDataset() && !p.isScopeAggregation())
183  {
185  "Got a nested <netcdf> element which was NOT a direct child of an <aggregation>!");
186  }
187 
188  // Tell the parser we got a new current dataset.
189  // If this is the root, it also needs to set up our response!!
190  p.pushCurrentDataset(this);
191 
192  // Make sure the attributes that are set are valid for context
193  // that we just pushed.
194  validateAttributeContextOrThrow();
195  }
196 
197  void
198  NetcdfElement::handleContent(const string& content)
199  {
200  if (!NCMLUtil::isAllWhitespace(content))
201  {
203  "Got non-whitespace for element content and didn't expect it. Element=" + toString() + " content=\"" +
204  content + "\"");
205  }
206  }
207 
208  void
210  {
211  BESDEBUG("ncml", "NetcdfElement::handleEnd called!" << endl);
212 
213  if (!_parser->isScopeNetcdf())
214  {
216  "Got close of <netcdf> node while not within one!");
217  }
218 
219  // If we had an aggregation, we must tell it to finish any post-processing that
220  // it needs to do to make the aggregations correct (like add Grid map vectors
221  // for new dimensions)
222  if (_aggregation.get())
223  {
224  _aggregation->processParentDatasetComplete();
225  }
226 
227  // At this point, any deferred new variables MUST have their values set
228  // to preserve an invariant (and avoid cryptic internal error in libdap).
229  // So validate any deferred new variables now:
230  _variableValidator.validate(); // throws parse error if failure....
231 
232  // Tell the parser to close the current dataset and figure out what the new current one is!
233  // We pass our ptr to make sure that we're the current one to avoid logic bugs!!
234  _parser->popCurrentDataset(this);
235 
236 
237  // We'll leave our element table around until we're destroyed since people are allowed to use it if they
238  // maintained a ref to us....
239  }
240 
241  string
243  {
244  return "<" + _sTypeName + " " +
245  "location=\"" + _location + "\"" + // always print this one even in empty.
246  printAttributeIfNotEmpty("id", _id) +
247  printAttributeIfNotEmpty("title", _title) +
248  printAttributeIfNotEmpty("enhance", _enhance) +
249  printAttributeIfNotEmpty("addRecords", _addRecords) +
250  printAttributeIfNotEmpty("ncoords", _ncoords) +
251  printAttributeIfNotEmpty("coordValue", _coordValue) +
252  printAttributeIfNotEmpty("fmrcDefinition", _fmrcDefinition) +
253  ">";
254  }
255 
256  const libdap::DDS*
258  {
259  return const_cast<NetcdfElement*>(this)->getDDS();
260  }
261 
262  libdap::DDS*
264  {
265  // lazy eval loading the dds
266  if (!_loaded)
267  {
268  BESDEBUG("ncml", "Lazy loading DDX for location=" << location() << endl);
269  loadLocation();
270  }
271 
272  if (_response)
273  {
274  return NCMLUtil::getDDSFromEitherResponse(_response);
275  }
276  else
277  {
278  return 0;
279  }
280  }
281 
282  bool
284  {
285  // Right now we need these ptrs valid to be ready...
286  // Technically handleBegin() sets the parser,
287  // so we're not ready until after that has successfully completed.
288  return _response && _parser;
289  }
290 
291  unsigned int
293  {
295  "NetcdfElement::getNCoords(): called illegally when no ncoords attribute was specified!");
296  unsigned int num = 0;
297  if (!NCMLUtil::toUnsignedInt(_ncoords, num))
298  {
300  "A <netcdf> element has an invalid ncoords attribute set. Bad value was:"
301  "\"" + _ncoords + "\"");
302  }
303  return num;
304  }
305 
306  void
308  {
309  NCML_ASSERT_MSG(!_response, "_response object should be NULL for proper logic of borrowResponseObject call!");
310  _response = pResponse;
311  _weOwnResponse = false;
312  }
313 
314  void
316  {
317  NCML_ASSERT_MSG(pResponse == _response, "NetcdfElement::unborrowResponseObject() called with a response we are not borrowing.");
318  _response = 0;
319  }
320 
321  void
323  {
324  if (_response)
325  {
326  THROW_NCML_INTERNAL_ERROR("NetcdfElement::createResponseObject(): Called when we already had a _response! Logic error!");
327  }
328 
330 
331  // Make a new response and store the raw ptr, noting that we need to delete it in dtor.
332  std::auto_ptr<BESDapResponse> newResponse = _parser->getDDSLoader().makeResponseForType(type);
333  VALID_PTR(newResponse.get());
334  _response = newResponse.release();
335  _weOwnResponse = true;
336  }
337 
340  {
341  // If not created yet, make a new
342  // one in an RCPtr, store a weak ref,
343  // and return it.
344  RCPtr<AggMemberDataset> pAGM(0);
345  if (_pDatasetWrapper.empty())
346  {
347  if (_location.empty())
348  {
349  // if the location is empty, we must assume we have a valid DDS
350  // that has been created virtually or as a nested aggregation
351  // We create a wrapper for the NetcdfElement in this case
352  // using the ref-counted DDS accessor interface.
353  const DDSAccessRCInterface* pDDSHolder = this;
355  }
356  else
357  {
359  _location,
360  _parser->getDDSLoader());
361  }
362 
363  VALID_PTR(pAGM.get());
364 
365  // Make a weak ref to it, semantically const
366  const_cast<NetcdfElement*>(this)->_pDatasetWrapper = WeakRCPtr<AggMemberDataset>(pAGM.get());
367  }
368 
369  // Either way the weak ref is valid here, so return a new RCPtr to it
370  NCML_ASSERT(!_pDatasetWrapper.empty());
371  return _pDatasetWrapper.lock();
372  }
373 
374  const DimensionElement*
375  NetcdfElement::getDimensionInLocalScope(const string& name) const
376  {
377  const DimensionElement* ret = 0;
378  vector<DimensionElement*>::const_iterator endIt = _dimensions.end();
379  for (vector<DimensionElement*>::const_iterator it = _dimensions.begin(); it != endIt; ++it)
380  {
381  const DimensionElement* pElt = *it;
382  VALID_PTR(pElt);
383  if (pElt->name() == name)
384  {
385  ret = pElt;
386  break;
387  }
388  }
389  return ret;
390  }
391 
392  const DimensionElement*
393  NetcdfElement::getDimensionInFullScope(const string& name) const
394  {
395  // Base case...
396  const DimensionElement* elt = 0;
397  elt = getDimensionInLocalScope(name);
398  if (!elt)
399  {
400  NetcdfElement* parentDataset = getParentDataset();
401  if (parentDataset)
402  {
403  elt = parentDataset->getDimensionInFullScope(name);
404  }
405  }
406  return elt;
407  }
408 
409  void
411  {
412  VALID_PTR(dim);
413  if (getDimensionInLocalScope(dim->name()))
414  {
415  THROW_NCML_INTERNAL_ERROR("NCMLParser::addDimension(): already found dimension with name while adding " + dim->toString());
416  }
417 
418  _dimensions.push_back(dim);
419  dim->ref(); // strong reference!
420 
421  BESDEBUG("ncml", "Added dimension to dataset. Dimension Table is now: " << printDimensions() << endl);
422  }
423 
424  string
426  {
427  string ret ="Dimensions = {\n";
428  vector<DimensionElement*>::const_iterator endIt = _dimensions.end();
429  vector<DimensionElement*>::const_iterator it;
430  for (it = _dimensions.begin(); it != endIt; ++it)
431  {
432  ret += (*it)->toString() + "\n";
433  }
434  ret += "}";
435  return ret;
436  }
437 
438  void
440  {
441  while (!_dimensions.empty())
442  {
443  DimensionElement* elt = _dimensions.back();
444  elt->unref();
445  _dimensions.pop_back();
446  }
447  _dimensions.resize(0);
448  }
449 
450  const std::vector<DimensionElement*>&
452  {
453  return _dimensions;
454  }
455 
456  void
457  NetcdfElement::setChildAggregation(AggregationElement* agg, bool throwIfExists/*=true*/)
458  {
459  if (_aggregation.get() && throwIfExists)
460  {
461  THROW_NCML_INTERNAL_ERROR("NetcdfElement::setAggregation: We were called but we already contain a non-NULL aggregation! Previous="
462  + _aggregation->toString() + " and the new one is: " + agg->toString());
463  }
464 
465  // Otherwise, we can just set it and rely on the smart pointer to do the right thing
466  _aggregation = agg; // this will implicitly convert the raw ptr to a smart ptr
467 
468  // Also set a weak reference to this as the parent of the aggregation for walking up the tree...
469  _aggregation->setParentDataset(this);
470  }
471 
474  {
475  NetcdfElement* ret = 0;
476  if (_parentAgg && _parentAgg->getParentDataset())
477  {
478  ret = _parentAgg->getParentDataset();
479  }
480  return ret;
481  }
482 
485  {
486  return _parentAgg;
487  }
488 
489  void
491  {
492  _parentAgg = parent;
493  }
494 
497  {
498  return _aggregation.get();
499  }
500 
501 
502 #if 0 // not sure we need this yet...
503  template <typename T>
504  int
505  NetcdfElement::getCoordValueVector(vector<T>& values) const
506  {
507  // clear it out just in case.
508  values.resize(0);
509 
510  // first, tokenize into strings
511  vector<string> tokens;
512  int numToks = NCMLUtil::tokenize(_coordValue, tokens, NCMLUtil::WHITESPACE);
513  values.reserve(numToks);
514 
515  for (int i=0; i<numToks; ++i)
516  {
517  stringstream iss(tokens[i]);
518  T val;
519  iss >> val;
520  if (iss.fail())
521  {
523  "NetcdfElement::getCoordValueVector(): "
524  "Could not parse the token \"" + tokens[i] + "\""
525  " into the required data type.");
526  }
527  else
528  {
529  values.push_back(val);
530  }
531  }
532  }
533 #endif
534 
535  bool
537  {
538  if (_coordValue.empty())
539  {
540  return false;
541  }
542 
543  std::istringstream iss(_coordValue);
544  double num;
545  iss >> num;
546  // eof() to make sure we parsed it all. >> can stop early on malformedness.
547  if (iss.fail() || !iss.eof() )
548  {
549  return false;
550  }
551  else
552  {
553  val = num;
554  return true;
555  }
556  }
557 
558  void
560  {
561  _variableValidator.addVariableToValidate(pNewVar, pVE);
562  }
563 
564  void
565  NetcdfElement::setVariableGotValues(libdap::BaseType* pVarToValidate, bool removeEntry)
566  {
567  _variableValidator.setVariableGotValues(pVarToValidate);
568  if (removeEntry)
569  {
570  _variableValidator.removeVariableToValidate(pVarToValidate);
571  }
572  }
573 
574 
575  /********** Class Methods ***********/
576 
577  bool
579  {
580  // args should never be null, but let's catch the error in dev if we goof.
581  // I don't want to use VALID_PTR here to avoid exception overhead in an internal
582  // sort function.
583  assert(pLHS);
584  assert(pRHS);
585  return (pLHS->location().compare(pRHS->location()) < 0);
586  }
587 
588 
589  bool
591  {
592  // args should never be null, but let's catch the error in dev if we goof.
593  // I don't want to use VALID_PTR here to avoid exception overhead in an internal
594  // sort function.
595  assert(pLHS);
596  assert(pRHS);
597  return (pLHS->coordValue().compare(pRHS->coordValue()) < 0);
598  }
599 
600 
603 
604  void
605  NetcdfElement::loadLocation()
606  {
607  if (_location.empty())
608  {
609  // nothing to load, so we're loaded I guess.
610  _loaded = true;
611  return;
612  }
613 
614  // We better have one! This gets created up front now. It will be an empty DDS
615  NCML_ASSERT_MSG(_response,
616  "NetcdfElement::loadLocation(): Requires a valid _response via borrowResponseObject() or createResponseObject() prior to call!");
617 
618  // Use the loader to load the location
619  // If not found, this call will throw an exception and we'll just unwind out.
620  if (_parser)
621  {
622  _parser->loadLocation(_location, _parser->_responseType, _response);
623  _loaded = true;
624  }
625  }
626 
627  void
628  NetcdfElement::throwOnUnsupportedAttributes()
629  {
630  const string msgStart = "NetcdfElement: unsupported attribute: ";
631  const string msgEnd = " was declared.";
632  if (!_enhance.empty())
633  {
635  msgStart + "enhance" + msgEnd);
636  }
637  if (!_addRecords.empty())
638  {
640  msgStart + "addRecords" + msgEnd);
641  }
642 
643  // not until fmrc
644  if (!_fmrcDefinition.empty())
645  {
647  msgStart + "fmrcDefinition" + msgEnd);
648  }
649  }
650 
651  bool
652  NetcdfElement::validateAttributeContextOrThrow() const
653  {
654  if (hasNcoords())
655  {
656  AggregationElement* pParentAgg = getParentAggregation();
657  if (!pParentAgg ||
658  !( pParentAgg->isJoinExistingAggregation()) )
659  {
661  "Cannot specify netcdf@ncoords attribute while not within a "
662  "joinExisting aggregation!");
663  }
664  }
665  return true;
666  }
667 
668  vector<string>
669  NetcdfElement::getValidAttributes()
670  {
671  vector<string> validAttrs;
672  validAttrs.reserve(9);
673 
674  validAttrs.push_back("location");
675  validAttrs.push_back("id");
676  validAttrs.push_back("title");
677  validAttrs.push_back("enhance");
678  validAttrs.push_back("addRecords");
679  // following only valid inside aggregation, will need to test for that later.
680  validAttrs.push_back("ncoords");
681  validAttrs.push_back("coordValue");
682  validAttrs.push_back("fmrcDefinition");
683 
684  return validAttrs;
685  }
686 
687  /******************** Inner Class Def of VariableValueValidator *********************/
688 
689  typedef vector<NetcdfElement::VariableValueValidator::VVVEntry> VVVEntries;
690 
692  : _entries()
693  , _pParent(pParent)
694  {
695  }
696 
698  {
699  // For each entry, deref the VariableElement and clear it out.
700  VVVEntries::iterator it;
701  VVVEntries::iterator endIt = _entries.end();
702  for (it = _entries.begin(); it != endIt; ++it)
703  {
704  VVVEntry& entry = *it;
705  entry._pVarElt->unref();
706  entry.clear();
707  }
708  _entries.resize(0);
709  }
710 
711  void
713  {
714  VALID_PTR(pNewVar);
715  VALID_PTR(pVE);
716  {
717  VVVEntry* pExisting = findEntryByLibdapVar(pNewVar);
718  NCML_ASSERT_MSG(!pExisting, "NetcdfElement::VariableValueValidator::addVariableToValidate: var was already added!");
719  }
720 
721  // Up the ref count to keep it around and add an entry for it
722  pVE->ref();
723  _entries.push_back(VVVEntry(pNewVar, pVE));
724  }
725 
726  void
728  {
729  for (unsigned int i=0; i<_entries.size(); ++i)
730  {
731  if (_entries[i]._pNewVar == pVarToRemove)
732  {
733  _entries[i]._pVarElt->unref();
734  _entries[i] = _entries[_entries.size()-1];
735  _entries.pop_back();
736  break;
737  }
738  }
739  }
740 
741  void
743  {
744  VALID_PTR(pVarToValidate);
745  VVVEntry* pEntry = findEntryByLibdapVar(pVarToValidate);
746  NCML_ASSERT_MSG(pEntry, "NetcdfElement::VariableValueValidator::setVariableGotValues: expected to find the var name=" +
747  pVarToValidate->name() + " but we did not!");
748  pEntry->_pVarElt->setGotValues();
749  }
750 
753  {
754  return _variableValidator.findVariableElementForLibdapVar(pNewVar);
755  }
756 
757  bool
759  {
760  VVVEntries::iterator it;
761  VVVEntries::iterator endIt = _entries.end();
762  for (it = _entries.begin(); it != endIt; ++it)
763  {
764  VVVEntry& entry = *it;
765  // If the values was never set...
766  if (!entry._pVarElt->checkGotValues())
767  {
768  THROW_NCML_PARSE_ERROR(_pParent->line(),
769  "On closing the <netcdf> element, we found a new variable name=" +
770  entry._pNewVar->name() +
771  " that was added"
772  " to the dataset but which never had values set on it. This is illegal!"
773  " Please make sure all variables in this dataset have values set on them"
774  " or that they are new coordinate variables for a joinNew aggregation.");
775  }
776  }
777  return true;
778  }
779 
781  NetcdfElement::VariableValueValidator::findEntryByLibdapVar(libdap::BaseType* pVarToFind)
782  {
783  VALID_PTR(pVarToFind);
784  VVVEntry* pRetVal = 0;
785  VVVEntries::iterator it;
786  VVVEntries::iterator endIt = _entries.end();
787  for (it = _entries.begin(); it != endIt; ++it)
788  {
789  VVVEntry& entry = *it;
790  if (entry._pNewVar == pVarToFind)
791  {
792  pRetVal = &entry;
793  break;
794  }
795  }
796  return pRetVal;
797  }
798 
799  VariableElement*
801  {
802  VALID_PTR(pVarToFind);
803  VVVEntry* pRetVal = findEntryByLibdapVar(pVarToFind);
804  if (pRetVal)
805  {
806  return pRetVal->_pVarElt;
807  }
808  else
809  {
810  return 0;
811  }
812  }
813 
814 } // namespace ncml_module
~VariableValueValidator()
Will decrement the ref count of all contained VariableElement's.
virtual const string & getTypeName() const
Return the type of the element, which should be: the same as ConcreteClassName::getTypeName() ...
static std::auto_ptr< BESDapResponse > makeResponseForType(ResponseType type)
Make a new response object for the requested type.
Definition: DDSLoader.cc:333
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...
Definition: NCMLElement.cc:191
void addVariableToValidateOnClose(libdap::BaseType *pNewVar, VariableElement *pVE)
Add the pNewvar created by pVE to this dataset's list of variables to validate for having values set ...
ResponseType
For telling the loader what type of BESDapResponse to load and return.
Definition: DDSLoader.h:97
virtual string toString() const
Return a string describing the element.
static bool isCoordValueLexicographicallyLessThan(const NetcdfElement *pLHS, const NetcdfElement *pRHS)
Compare the coordvalue fields of the two arguments and return true if lhs.coordValue() < rhs...
#define SAFE_DELETE(a)
Definition: NCMLUtil.h:64
class AggMemberDatasetUsingLocationRef: Concrete subclass of AggMemberDataset for lazy-loading a loca...
bool empty() const
Will getting a lock() return a null?
Definition: RCObject.h:453
const string & location() const
Definition: NetcdfElement.h:87
void setParentAggregation(AggregationElement *parent)
Set my parent AggregationElement to parent.
void addDimension(DimensionElement *dim)
Add the given element to this scope.
#define NCML_ASSERT(cond)
Definition: NCMLDebug.h:80
void setChildAggregation(AggregationElement *agg, bool throwIfExists=true)
Set our aggregation to the given agg.
virtual int unref() const
Decrease the reference count by one.
Definition: RCObject.cc:82
An abstract superclass for NCMLArray that handles the non-parameterized functionality and allows u...
STL namespace.
const string & coordValue() const
Definition: NetcdfElement.h:90
void clearDimensions()
Clear the dimension table, releasing all strong references.
virtual void handleEnd()
Handle the closing of this element.
Helper class for temporarily hijacking an existing dhi to load a DDX response for one particular file...
const string getValueForLocalNameOrDefault(const string &localname, const string &defVal="") const
If there is an attribute with localname, return its value, else return default.
Definition: XMLHelpers.cc:209
static bool isAllWhitespace(const std::string &str)
Is all the string whitespace as defined by chars in WHITESPACE ?
Definition: NCMLUtil.cc:110
static libdap::DDS * getDDSFromEitherResponse(BESDapResponse *response)
Return the DDS* for the given response object.
Definition: NCMLUtil.cc:282
#define assert(exp)
Definition: freeform.h:735
virtual void handleContent(const string &content)
Handle the characters content for the element.
#define NCML_ASSERT_MSG(cond, msg)
Definition: NCMLDebug.h:83
Concrete class for NcML element.
Definition: NetcdfElement.h:63
static bool toUnsignedInt(const std::string &stringVal, unsigned int &oVal)
Convert the string to an unsigned int into oVal.
Definition: NCMLUtil.cc:146
Interface class for any object that can contains a DDS.
virtual const libdap::DDS * getDDS() const
Return the DDS for this dataset, loading it in if needed.
const DimensionElement * getDimensionInLocalScope(const string &name) const
static const vector< string > _sValidAttributes
Definition: NetcdfElement.h:72
static const string _sTypeName
Definition: NetcdfElement.h:71
virtual NetcdfElement * clone() const
Make and return a copy of this.
void setVariableGotValues(libdap::BaseType *pVarToValidate)
Lookup the VariableElement pVE associated with the given pVarToValidate and call pVE->setGotValues() ...
RCPtr< agg_util::AggMemberDataset > getAggMemberDataset() const
Return a shared reference to the AggMemberDataset that encapsulates this dataset. ...
string printDimensions() const
"Print" out the dimensions to a string
bool validate()
Make sure all the entries has had their values set else throw a parse error explaining which variable...
virtual string toString() const
Return a string describing the element.
static bool isLocationLexicographicallyLessThan(const NetcdfElement *pLHS, const NetcdfElement *pRHS)
Compare the location fields of the two arguments and return true if lhs.location() < rhs...
AggregationElement * getChildAggregation() const
Return the raw pointer (or NULL) to our contained aggregation.
virtual void handleBegin()
Handle a begin on this element.
class AggMemberDatasetSharedDDSWrapper: concrete subclass of AggMemberDataset designed to hold a ref-...
Mixture interface for when we a reference-counted DDS container.
int getParseLineNumber() const
Get the line of the NCML file the parser is currently parsing.
Definition: NCMLParser.cc:222
static std::string printAttributeIfNotEmpty(const std::string &attrName, const std::string &attrValue)
Helper for subclasses implementing toString().
Definition: NCMLElement.cc:240
const std::vector< DimensionElement * > & getDimensionElements() const
Get the list of dimension elements local to only this dataset, not its enclosing scope.
RCPtr< T > lock() const
Definition: RCObject.h:458
NetcdfElement * getParentDataset() const
const DimensionElement * getDimensionInFullScope(const string &name) const
#define THROW_NCML_PARSE_ERROR(parseLine, msg)
Definition: NCMLDebug.h:69
virtual int ref() const
Increase the reference count by one.
Definition: RCObject.cc:74
void removeVariableToValidate(libdap::BaseType *pVarToRemove)
Remove an entry previously added under the key pVarToRemove with addVariableToValidate.
void createResponseObject(agg_util::DDSLoader::ResponseType type)
Called if this is a member of an aggregation (i.e.
unsigned int getNcoordsAsUnsignedInt() const
Get the ncoords() field as a valid size.
A reference to an RCObject which automatically ref() and deref() on creation and destruction.
Definition: RCObject.h:279
bool getCoordValueAsDouble(double &val) const
Parse the netcdf attribute as a double.
VariableElement * findVariableElementForLibdapVar(libdap::BaseType *pNewVar)
If a VariableElement has been associated with a new var to validate, return it.
void setVariableGotValues(libdap::BaseType *pVarToValidate, bool removeEntry)
Lookup the VariableElement* associated with pVarToValidate via a previous addVariableToValidateOnClos...
void unborrowResponseObject(BESDapResponse *pResponse)
Kind of superfluous, but tells this object to clear its reference to pReponse, which had better match...
Base class for NcML element concrete classes.
Definition: NCMLElement.h:64
virtual DimensionElement * clone() const
Make and return a copy of this.
int line() const
Return the current parse line number.
Definition: NCMLElement.cc:174
Represents an OPeNDAP DAP response object within the BES.
#define THROW_NCML_INTERNAL_ERROR(msg)
Definition: NCMLDebug.h:61
Concrete class for NcML element.
virtual void setAttributes(const XMLAttributeMap &attrs)
Set the attributes of this from the map.
vector< NetcdfElement::VariableValueValidator::VVVEntry > VVVEntries
AggregationElement * getParentAggregation() const
A variant of boost::weak_ptr that uses our intrusive RCObject counting.
Definition: RCObject.h:412
#define VALID_PTR(ptr)
Definition: NCMLDebug.h:88
T * get() const
Definition: RCObject.h:334
void addVariableToValidate(libdap::BaseType *pNewVar, VariableElement *pVE)
Add a validation entry for the given VariableElement and the actual variable that it has created and ...
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
NetcdfElement * getParentDataset() const
Return the next enclosing dataset for this, or NULL if we're the root.
virtual string toString() const
Return a string describing the element.
static const std::string WHITESPACE
Delimiter set for tokenizing whitespace separated data.
Definition: NCMLUtil.h:79
void borrowResponseObject(BESDapResponse *pResponse)
Used by the NCMLParser to let us know to borrow the response object and not own it.
void setGotValues()
Called once we set the values from ValuesElement so we are aware.
Interface class for a reference counted object.
static int tokenize(const std::string &str, std::vector< std::string > &tokens, const std::string &delimiters=" \t")
Split str into tokens using the characters in delimiters as split boundaries.
Definition: NCMLUtil.cc:54
const string & name() const
VariableElement * findVariableElementForLibdapVar(libdap::BaseType *pNewVar)
If a VariableElement has been associated with a new var to validate, return it.