bes  Updated for version 3.20.5
NCMLParser.h
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 #ifndef __NCML_MODULE_NCML_PARSER_H__
31 #define __NCML_MODULE_NCML_PARSER_H__
32 
33 #include "config.h"
34 
35 #include <memory>
36 #include <stack>
37 #include <string>
38 #include <vector>
39 
40 #include <AttrTable.h> // needed due to parameter with AttrTable::Attr_iter
41 
42 #include "DDSLoader.h"
43 #include "NCMLElement.h" // NCMLElement::Factory
44 #include "SaxParser.h" // interface superclass
45 #include "ScopeStack.h"
46 #include "XMLHelpers.h"
47 
48 //FDecls
49 
50 namespace agg_util {
51 class DDSLoader;
52 }
53 
54 namespace libdap {
55 class BaseType;
56 class DAS;
57 class DDS;
58 }
59 
60 class BESDapResponse;
61 class BESDataDDSResponse;
62 class BESDDSResponse;
63 
64 namespace ncml_module {
65 class AggregationElement;
66 class DimensionElement;
67 class NCMLElement;
68 class NetcdfElement;
69 class OtherXMLParser;
70 }
71 
72 using namespace libdap;
73 using namespace std;
74 
114 namespace ncml_module {
115 
116 // FDecls
117 class NCMLParser;
118 
119 // Helper class to lazy load the AttrTable for a DDS so we don't load for aggregations
120 // that do not actually use it.
122 private:
123  // disallow these.
125  AttrTableLazyPtr& operator=(const AttrTableLazyPtr&);
126 public:
133  AttrTableLazyPtr(const NCMLParser& parser, AttrTable* pAT = 0);
134  ~AttrTableLazyPtr();
135 
140  AttrTable* get() const;
141 
143  void set(AttrTable* pAT);
144 
148  void invalidate();
149 
150 private:
151 
152  void loadAndSetAttrTable();
153 
154  const NCMLParser& _parser;
155  mutable AttrTable* _pAttrTable;
156  mutable bool _loaded;
157 };
158 
159 class NCMLParser: public SaxParser {
160 public:
161  // Friends
162  // We allow the various NCMLElement concrete classes to be friends so we can separate out the functionality
163  // into several files, one for each NcML element type.
164  friend class AggregationElement;
165  friend class AttrTableLazyPtr;
166  friend class AttributeElement;
167  friend class DimensionElement;
168  friend class ExplicitElement;
169  friend class NetcdfElement;
170  friend class ReadMetadataElement;
171  friend class RemoveElement;
172  friend class ScanElement;
173  friend class ValuesElement;
174  friend class VariableAggElement;
175  friend class VariableElement;
176 
177 public:
185 
186  virtual ~NCMLParser();
187 
188 private:
190  NCMLParser(const NCMLParser& from);
191 
193  NCMLParser& operator=(const NCMLParser& from);
194 
195 public:
196 
206  auto_ptr<BESDapResponse> parse(const string& ncmlFilename, agg_util::DDSLoader::ResponseType type);
207 
215  void parseInto(const string& ncmlFilename, agg_util::DDSLoader::ResponseType responseType,
216  BESDapResponse* response);
217 
219  bool parsing() const;
220 
222  int getParseLineNumber() const;
223 
225  const XMLNamespaceStack& getXMLNamespaceStack() const;
226 
228  // Interface SaxParser: Wrapped calls from the libxml C SAX parser
229 
230  virtual void onStartDocument();
231  virtual void onEndDocument();
232  virtual void onStartElement(const std::string& name, const XMLAttributeMap& attrs);
233  virtual void onEndElement(const std::string& name);
234 
235  virtual void onStartElementWithNamespace(const std::string& localname, const std::string& prefix,
236  const std::string& uri, const XMLAttributeMap& attributes, const XMLNamespaceMap& namespaces);
237 
238  virtual void onEndElementWithNamespace(const std::string& localname, const std::string& prefix,
239  const std::string& uri);
240 
241  virtual void onCharacters(const std::string& content);
242  virtual void onParseWarning(std::string msg);
243  virtual void onParseError(std::string msg);
244  virtual void setParseLineNumber(int line);
245 
248 
249 private:
250  //methods
251 
253  bool isScopeAtomicAttribute() const;
254 
256  bool isScopeAttributeContainer() const;
257 
259  bool isScopeSimpleVariable() const;
260 
262  bool isScopeCompositeVariable() const;
263 
265  bool isScopeVariable() const;
266 
268  bool isScopeGlobal() const;
269 
271  bool isScopeNetcdf() const;
272 
274  bool isScopeAggregation() const;
275 
279  bool withinNetcdf() const;
280 
285  bool withinVariable() const;
286 
287  agg_util::DDSLoader& getDDSLoader() const;
288 
292  NetcdfElement* getCurrentDataset() const;
293 
306  void setCurrentDataset(NetcdfElement* dataset);
307 
309  NetcdfElement* getRootDataset() const;
310 
313  DDS* getDDSForCurrentDataset() const;
314 
322  void pushCurrentDataset(NetcdfElement* dataset);
323 
331  void addChildDatasetToCurrentDataset(NetcdfElement* dataset);
332 
339  void popCurrentDataset(NetcdfElement* dataset);
340 
344  bool parsingDataRequest() const;
345 
349  void resetParseState();
350 
354  void loadLocation(const std::string& location, agg_util::DDSLoader::ResponseType responseType,
355  BESDapResponse* response);
356 
358  bool isNameAlreadyUsedAtCurrentScope(const std::string& name);
359 
367  BaseType* getVariableInCurrentVariableContainer(const string& name);
368 
376  BaseType* getVariableInContainer(const string& varName, BaseType* pContainer);
377 
385  BaseType* getVariableInDDS(const string& varName);
386 
401  void addCopyOfVariableAtCurrentScope(BaseType& varTemplate);
402 
407  void deleteVariableAtCurrentScope(const string& name);
408 
412  BaseType* getCurrentVariable() const;
413 
418  void setCurrentVariable(BaseType* pVar);
419 
426  static bool typeCheckDAPVariable(const BaseType& var, const string& expectedType);
427 
436  AttrTable* getCurrentAttrTable() const;
437 
443  void setCurrentAttrTable(AttrTable* pAT);
444 
449  AttrTable* getGlobalAttrTable() const;
450 
455  bool attributeExistsAtCurrentScope(const string& name) const;
456 
462  bool findAttribute(const string& name, AttrTable::Attr_iter& attr) const;
463 
467  void clearAllAttrTables(DDS* dds);
468 
470  void clearVariableMetadataRecursively(BaseType* var);
471 
477  int tokenizeAttrValues(vector<string>& tokens, const string& values, const string& dapAttrTypeName,
478  const string& separator);
479 
488  int tokenizeValuesForDAPType(vector<string>& tokens, const string& values, AttrType dapType,
489  const string& separator);
490 
492  void enterScope(const string& name, ScopeStack::ScopeType type);
493 
495  void exitScope();
496 
498  void printScope() const;
499 
501  string getScopeString() const;
502 
504  string getTypedScopeString() const;
505 
507  int getScopeDepth() const;
508 
511  void pushElement(NCMLElement* elt);
512 
516  void popElement();
517 
519  NCMLElement* getCurrentElement() const;
520 
523  typedef std::vector<NCMLElement*>::const_reverse_iterator ElementStackConstIterator;
524  ElementStackConstIterator getElementStackBegin() const
525  {
526  return _elementStack.rbegin();
527  }
528  ElementStackConstIterator getElementStackEnd() const
529  {
530  return _elementStack.rend();
531  }
532 
536  void clearElementStack();
537 
539  void processStartNCMLElement(const std::string& name, const XMLAttributeMap& attrs);
540 
542  void processEndNCMLElement(const std::string& name);
543 
547  const DimensionElement* getDimensionAtLexicalScope(const string& dimName) const;
548 
553  string printAllDimensionsAtLexicalScope() const;
554 
568  void enterOtherXMLParsingState(OtherXMLParser* pOtherXMLParser);
569  bool isParsingOtherXML() const;
570 
572  void cleanup();
573 
574 public:
575  // Class Helpers
576 
578  static const string STRUCTURE_TYPE;
579 
591  static string convertNcmlTypeToCanonicalType(const string& ncmlType);
592 
600  void checkDataIsValidForCanonicalTypeOrThrow(const string& type, const vector<string>& tokens) const;
601 
603 private:
604  // data rep
605 
606  // If true, we will consider unknown ncml elements as parse errors and raise exception.
607  // If false, we just BESDEBUG the warning and ignore them entirely.
608  static bool sThrowExceptionOnUnknownElements;
609 
610  // name of the ncml file we are parsing
611  string _filename;
612 
613  // Handed in at creation, this is a helper to load a given DDS. It is assumed valid for the life of this.
614  agg_util::DDSLoader& _loader;
615 
616  // The type of response in _response
617  agg_util::DDSLoader::ResponseType _responseType;
618 
619  // The response object containing the DDS (or DataDDS) for the root dataset we are processing, or null if not processing.
620  // Type is based on _responseType. We do not own this memory! It is a temp while we parse and is handed in.
621  // NOTE: The root dataset will use this for its response object!
622  BESDapResponse* _response;
623 
624  // The element factory to use to create our NCMLElement's.
625  // All objects created by this factory will be deleted in the dtor
626  // regardless of their ref counts!
627  NCMLElement::Factory _elementFactory;
628 
629  // The root dataset, as a NetcdfElement*.
630  NetcdfElement* _rootDataset;
631 
632  // The currently being parsed dataset, as a NetcdfElement
633  NetcdfElement* _currentDataset;
634 
635  // pointer to currently processed variable, or NULL if none (ie we're at global level).
636  BaseType* _pVar;
637 
638  // Only grabs the actual ptr (by loading the DDS from the current dataset)
639  // when getCurrentAttrTable() is called so we don't explicitly load every
640  // DDS, only those which we want to modify.
641  AttrTableLazyPtr _pCurrentTable;
642 
643  // A stack of NcML elements we push as we begin and pop as we end.
644  // The memory is owned by this, so we must clear this in dtor and
645  // on pop.
646  std::vector<NCMLElement*> _elementStack;
647 
648  // As we parse, we'll use this as a stack for keeping track of the current
649  // scope we're in. In other words, this stack will refer to the container where _pCurrTable is in the DDS.
650  // if empty() then we're in global dataset scope (or no scope if not parsing location yet).
651  ScopeStack _scope;
652 
653  // Keeps track of the XMLNamespace's that come in with each new
654  // onStartElementWithNamespace and gets popped on
655  // onEndElementWithNamespace.
656  XMLNamespaceStack _namespaceStack;
657 
658  // If not null, we've temporarily stopped the normal NCML parse and are passing
659  // all calls to this proxy until the element on the stack when it was added is
660  // closed (and the parser depth is zero!).
661  OtherXMLParser* _pOtherXMLParser;
662 
663  // Where we are in the parse to help debugging, set from the SaxParser interface.
664  int _currentParseLine;
665 
666 };
667 // class NCMLParser
668 
669 }//namespace ncml_module
670 
671 #endif /* __NCML_MODULE_NCML_PARSER_H__ */
agg_util::DDSLoader
Definition: DDSLoader.h:62
BESDapResponse
Represents an OPeNDAP DAP response object within the BES.
Definition: BESDapResponse.h:41
ncml_module::NetcdfElement
Concrete class for NcML <netcdf> element.
Definition: NetcdfElement.h:62
ncml_module::ScopeStack
Definition: ScopeStack.h:56
ncml_module::ScopeStack::ScopeType
ScopeType
Definition: ScopeStack.h:63
ncml_module::AttributeElement
Concrete class for NcML <attribute> element.
Definition: AttributeElement.h:53
ncml_module::XMLNamespaceStack
Definition: XMLHelpers.h:195
ncml_module::NCMLParser
Definition: NCMLParser.h:159
ncml_module::RemoveElement
Definition: RemoveElement.h:40
ncml_module::AttrTableLazyPtr
Definition: NCMLParser.h:121
ncml_module::XMLAttributeMap
Definition: XMLHelpers.h:96
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::OtherXMLParser
Definition: OtherXMLParser.h:47
ncml_module::ScanElement
Definition: ScanElement.h:48
ncml_module::ValuesElement
Definition: ValuesElement.h:49
ncml_module::VariableAggElement
Element for the <variableAgg> element child of an <aggregation>.
Definition: VariableAggElement.h:41
ncml_module::DimensionElement
Definition: DimensionElement.h:55
libdap
Definition: BESDapFunctionResponseCache.h:35
ncml_module::ExplicitElement
Concrete class for NcML <explicit> element.
Definition: ExplicitElement.h:41
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:62
ncml_module::NCMLElement::Factory
Definition: NCMLElement.h:73
ncml_module::NCMLElement
Base class for NcML element concrete classes.
Definition: NCMLElement.h:63
BESDDSResponse
Holds a DDS object within the BES.
Definition: BESDDSResponse.h:50
BESDataDDSResponse
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
Definition: BESDataDDSResponse.h:46
ncml_module
NcML Parser for adding/modifying/removing metadata (attributes) to existing local datasets using NcML...
Definition: AggregationElement.cc:72
ncml_module::ReadMetadataElement
Concrete class for NcML <readMetadata> element.
Definition: ReadMetadataElement.h:43
ncml_module::NCMLParser::STRUCTURE_TYPE
static const string STRUCTURE_TYPE
Definition: NCMLParser.h:578
ncml_module::XMLNamespaceMap
Definition: XMLHelpers.h:153
ncml_module::SaxParser
Interface class for the wrapper between libxml C SAX parser and our NCMLParser.
Definition: SaxParser.h:48