OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
NCMLParser.h
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 #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 {
52  class DDSLoader;
53 };
54 
55 namespace libdap
56 {
57  class BaseType;
58  class DAS;
59  class DDS;
60 };
61 class BESDapResponse;
62 
63 class BESDataDDSResponse;
64 class BESDDSResponse;
65 
66 namespace ncml_module
67 {
68  class AggregationElement;
69  class DimensionElement;
70  class NCMLElement;
71  class NetcdfElement;
72  class OtherXMLParser;
73 }
74 
75 using namespace libdap;
76 using namespace std;
77 
78 
118 namespace ncml_module
119 {
120 
121  // FDecls
122  class NCMLParser;
123 
124 // Helper class to lazy load the AttrTable for a DDS so we don't load for aggregations
125 // that do not actually use it.
127 {
128 private: // disallow these.
130  AttrTableLazyPtr& operator=(const AttrTableLazyPtr&);
131 public:
138  AttrTableLazyPtr(const NCMLParser& parser, AttrTable* pAT=0);
139  ~AttrTableLazyPtr();
140 
145  AttrTable* get() const;
146 
148  void set(AttrTable* pAT);
149 
153  void invalidate();
154 
155 private:
156 
157  void loadAndSetAttrTable();
158 
159  const NCMLParser& _parser;
160  mutable AttrTable* _pAttrTable;
161  mutable bool _loaded;
162 };
163 
164 class NCMLParser : public SaxParser
165 {
166 public: // Friends
167  // We allow the various NCMLElement concrete classes to be friends so we can separate out the functionality
168  // into several files, one for each NcML element type.
169  friend class AggregationElement;
170  friend class AttrTableLazyPtr;
171  friend class AttributeElement;
172  friend class DimensionElement;
173  friend class ExplicitElement;
174  friend class NetcdfElement;
175  friend class ReadMetadataElement;
176  friend class RemoveElement;
177  friend class ScanElement;
178  friend class ValuesElement;
179  friend class VariableAggElement;
180  friend class VariableElement;
181 
182 public:
190 
191  virtual ~NCMLParser();
192 
193 private:
195  NCMLParser(const NCMLParser& from);
196 
198  NCMLParser& operator=(const NCMLParser& from);
199 
200 public:
201 
211  auto_ptr<BESDapResponse> parse(const string& ncmlFilename, agg_util::DDSLoader::ResponseType type);
212 
220  void parseInto(const string& ncmlFilename, agg_util::DDSLoader::ResponseType responseType, BESDapResponse* response);
221 
223  bool parsing() const;
224 
226  int getParseLineNumber() const;
227 
229  const XMLNamespaceStack& getXMLNamespaceStack() const;
230 
232  // Interface SaxParser: Wrapped calls from the libxml C SAX parser
233 
234  virtual void onStartDocument();
235  virtual void onEndDocument();
236  virtual void onStartElement(const std::string& name, const XMLAttributeMap& attrs);
237  virtual void onEndElement(const std::string& name);
238 
239  virtual void onStartElementWithNamespace(
240  const std::string& localname ,
241  const std::string& prefix,
242  const std::string& uri,
243  const XMLAttributeMap& attributes,
244  const XMLNamespaceMap& namespaces);
245 
246  virtual void onEndElementWithNamespace(
247  const std::string& localname,
248  const std::string& prefix,
249  const std::string& uri);
250 
251  virtual void onCharacters(const std::string& content);
252  virtual void onParseWarning(std::string msg);
253  virtual void onParseError(std::string msg);
254  virtual void setParseLineNumber(int line);
255 
258 
259 private: //methods
260 
262  bool isScopeAtomicAttribute() const;
263 
265  bool isScopeAttributeContainer() const;
266 
268  bool isScopeSimpleVariable() const;
269 
271  bool isScopeCompositeVariable() const;
272 
274  bool isScopeVariable() const;
275 
277  bool isScopeGlobal() const;
278 
280  bool isScopeNetcdf() const;
281 
283  bool isScopeAggregation() const;
284 
288  bool withinNetcdf() const;
289 
294  bool withinVariable() const;
295 
296  agg_util::DDSLoader& getDDSLoader() const;
297 
301  NetcdfElement* getCurrentDataset() const;
302 
315  void setCurrentDataset(NetcdfElement* dataset);
316 
318  NetcdfElement* getRootDataset() const;
319 
322  DDS* getDDSForCurrentDataset() const;
323 
331  void pushCurrentDataset(NetcdfElement* dataset);
332 
340  void addChildDatasetToCurrentDataset(NetcdfElement* dataset);
341 
348  void popCurrentDataset(NetcdfElement* dataset);
349 
353  bool parsingDataRequest() const;
354 
358  void resetParseState();
359 
363  void loadLocation(const std::string& location, agg_util::DDSLoader::ResponseType responseType, BESDapResponse* response);
364 
366  bool isNameAlreadyUsedAtCurrentScope(const std::string& name);
367 
375  BaseType* getVariableInCurrentVariableContainer(const string& name);
376 
384  BaseType* getVariableInContainer(const string& varName, BaseType* pContainer);
385 
393  BaseType* getVariableInDDS(const string& varName);
394 
409  void addCopyOfVariableAtCurrentScope(BaseType& varTemplate);
410 
415  void deleteVariableAtCurrentScope(const string& name);
416 
420  BaseType* getCurrentVariable() const;
421 
426  void setCurrentVariable(BaseType* pVar);
427 
434  static bool typeCheckDAPVariable(const BaseType& var, const string& expectedType);
435 
444  AttrTable* getCurrentAttrTable() const;
445 
451  void setCurrentAttrTable(AttrTable* pAT);
452 
457  AttrTable* getGlobalAttrTable() const;
458 
463  bool attributeExistsAtCurrentScope(const string& name) const;
464 
470  bool findAttribute(const string& name, AttrTable::Attr_iter& attr) const;
471 
475  void clearAllAttrTables(DDS* dds);
476 
478  void clearVariableMetadataRecursively(BaseType* var);
479 
485  int tokenizeAttrValues(vector<string>& tokens, const string& values, const string& dapAttrTypeName, const string& separator);
486 
495  int tokenizeValuesForDAPType(vector<string>& tokens, const string& values, AttrType dapType, const string& separator);
496 
498  void enterScope(const string& name, ScopeStack::ScopeType type);
499 
501  void exitScope();
502 
504  void printScope() const;
505 
507  string getScopeString() const;
508 
510  string getTypedScopeString() const;
511 
513  int getScopeDepth() const;
514 
517  void pushElement(NCMLElement* elt);
518 
522  void popElement();
523 
525  NCMLElement* getCurrentElement() const;
526 
529  typedef std::vector<NCMLElement*>::const_reverse_iterator ElementStackConstIterator;
530  ElementStackConstIterator getElementStackBegin() const { return _elementStack.rbegin(); }
531  ElementStackConstIterator getElementStackEnd() const { return _elementStack.rend(); }
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 
571 
573  void cleanup();
574 
575 public: // 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: // data rep
604 
605  // If true, we will consider unknown ncml elements as parse errors and raise exception.
606  // If false, we just BESDEBUG the warning and ignore them entirely.
607  static bool sThrowExceptionOnUnknownElements;
608 
609  // name of the ncml file we are parsing
610  string _filename;
611 
612  // Handed in at creation, this is a helper to load a given DDS. It is assumed valid for the life of this.
613  agg_util::DDSLoader& _loader;
614 
615  // The type of response in _response
616  agg_util::DDSLoader::ResponseType _responseType;
617 
618  // The response object containing the DDS (or DataDDS) for the root dataset we are processing, or null if not processing.
619  // Type is based on _responseType. We do not own this memory! It is a temp while we parse and is handed in.
620  // NOTE: The root dataset will use this for its response object!
621  BESDapResponse* _response;
622 
623  // The element factory to use to create our NCMLElement's.
624  // All objects created by this factory will be deleted in the dtor
625  // regardless of their ref counts!
626  NCMLElement::Factory _elementFactory;
627 
628  // The root dataset, as a NetcdfElement*.
629  NetcdfElement* _rootDataset;
630 
631  // The currently being parsed dataset, as a NetcdfElement
632  NetcdfElement* _currentDataset;
633 
634  // pointer to currently processed variable, or NULL if none (ie we're at global level).
635  BaseType* _pVar;
636 
637  // Only grabs the actual ptr (by loading the DDS from the current dataset)
638  // when getCurrentAttrTable() is called so we don't explicitly load every
639  // DDS, only those which we want to modify.
640  AttrTableLazyPtr _pCurrentTable;
641 
642  // A stack of NcML elements we push as we begin and pop as we end.
643  // The memory is owned by this, so we must clear this in dtor and
644  // on pop.
645  std::vector<NCMLElement*> _elementStack;
646 
647  // As we parse, we'll use this as a stack for keeping track of the current
648  // scope we're in. In other words, this stack will refer to the container where _pCurrTable is in the DDS.
649  // if empty() then we're in global dataset scope (or no scope if not parsing location yet).
650  ScopeStack _scope;
651 
652  // Keeps track of the XMLNamespace's that come in with each new
653  // onStartElementWithNamespace and gets popped on
654  // onEndElementWithNamespace.
655  XMLNamespaceStack _namespaceStack;
656 
657  // If not null, we've temporarily stopped the normal NCML parse and are passing
658  // all calls to this proxy until the element on the stack when it was added is
659  // closed (and the parser depth is zero!).
660  OtherXMLParser* _pOtherXMLParser;
661 
662  // Where we are in the parse to help debugging, set from the SaxParser interface.
663  int _currentParseLine;
664 
665 }; // class NCMLParser
666 
667 } //namespace ncml_module
668 
669 #endif /* __NCML_MODULE_NCML_PARSER_H__ */
Concrete class for NcML element.
ResponseType
For telling the loader what type of BESDapResponse to load and return.
Definition: DDSLoader.h:97
Factory class for the NcML elements.
Definition: NCMLElement.h:75
Represents an OPeNDAP DDS DAP2 data object within the BES.
An abstract superclass for NCMLArray that handles the non-parameterized functionality and allows u...
STL namespace.
Helper class for temporarily hijacking an existing dhi to load a DDX response for one particular file...
Concrete class for NcML element.
Definition: NetcdfElement.h:63
Implementation of the element used to scan directories to create the set of files for an aggre...
Definition: ScanElement.h:50
Concrete subclass for the NcML element.
Definition: RemoveElement.h:40
static class NCMLUtil overview
ScopeType
The current scope is either global attribute table, within a variable's attribute table...
Definition: ScopeStack.h:63
static const string STRUCTURE_TYPE
The string describing the type "Structure".
Definition: NCMLParser.h:578
Class used to handle parsing in an attribute of type=="OtherXML" which basically just has to keep app...
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
Base class for NcML element concrete classes.
Definition: NCMLElement.h:64
Represents an OPeNDAP DAP response object within the BES.
Concrete class for NcML element.
Concrete class for NcML element.
Concrete class for NcML element.
Element for the element child of an .
Interface class for the wrapper between libxml C SAX parser and our NCMLParser.
Definition: SaxParser.h:49