bes  Updated for version 3.20.6
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 
113 namespace ncml_module {
114 
115 // FDecls
116 class NCMLParser;
117 
118 // Helper class to lazy load the AttrTable for a DDS so we don't load for aggregations
119 // that do not actually use it.
121 private:
122  // disallow these.
124  AttrTableLazyPtr& operator=(const AttrTableLazyPtr&);
125 public:
132  AttrTableLazyPtr(const NCMLParser& parser, AttrTable* pAT = 0);
133  ~AttrTableLazyPtr();
134 
139  AttrTable* get() const;
140 
142  void set(AttrTable* pAT);
143 
147  void invalidate();
148 
149 private:
150 
151  void loadAndSetAttrTable();
152 
153  const NCMLParser& _parser;
154  mutable AttrTable* _pAttrTable;
155  mutable bool _loaded;
156 };
157 
158 class NCMLParser: public SaxParser {
159 public:
160  // Friends
161  // We allow the various NCMLElement concrete classes to be friends so we can separate out the functionality
162  // into several files, one for each NcML element type.
163  friend class AggregationElement;
164  friend class AttrTableLazyPtr;
165  friend class AttributeElement;
166  friend class DimensionElement;
167  friend class ExplicitElement;
168  friend class NetcdfElement;
169  friend class ReadMetadataElement;
170  friend class RemoveElement;
171  friend class ScanElement;
172  friend class ValuesElement;
173  friend class VariableAggElement;
174  friend class VariableElement;
175 
176 public:
184 
185  virtual ~NCMLParser();
186 
187 private:
189  NCMLParser(const NCMLParser& from);
190 
192  NCMLParser& operator=(const NCMLParser& from);
193 
194 public:
195 
205  std::auto_ptr<BESDapResponse> parse(const std::string& ncmlFilename, agg_util::DDSLoader::ResponseType type);
206 
214  void parseInto(const string& ncmlFilename, agg_util::DDSLoader::ResponseType responseType,
215  BESDapResponse* response);
216 
218  bool parsing() const;
219 
221  int getParseLineNumber() const;
222 
224  const XMLNamespaceStack& getXMLNamespaceStack() const;
225 
227  // Interface SaxParser: Wrapped calls from the libxml C SAX parser
228 
229  virtual void onStartDocument();
230  virtual void onEndDocument();
231  virtual void onStartElement(const std::string& name, const XMLAttributeMap& attrs);
232  virtual void onEndElement(const std::string& name);
233 
234  virtual void onStartElementWithNamespace(const std::string& localname, const std::string& prefix,
235  const std::string& uri, const XMLAttributeMap& attributes, const XMLNamespaceMap& namespaces);
236 
237  virtual void onEndElementWithNamespace(const std::string& localname, const std::string& prefix,
238  const std::string& uri);
239 
240  virtual void onCharacters(const std::string& content);
241  virtual void onParseWarning(std::string msg);
242  virtual void onParseError(std::string msg);
243  virtual void setParseLineNumber(int line);
244 
247 
248 private:
249  //methods
250 
252  bool isScopeAtomicAttribute() const;
253 
255  bool isScopeAttributeContainer() const;
256 
258  bool isScopeSimpleVariable() const;
259 
261  bool isScopeCompositeVariable() const;
262 
264  bool isScopeVariable() const;
265 
267  bool isScopeGlobal() const;
268 
270  bool isScopeNetcdf() const;
271 
273  bool isScopeAggregation() const;
274 
278  bool withinNetcdf() const;
279 
284  bool withinVariable() const;
285 
286  agg_util::DDSLoader& getDDSLoader() const;
287 
291  NetcdfElement* getCurrentDataset() const;
292 
305  void setCurrentDataset(NetcdfElement* dataset);
306 
308  NetcdfElement* getRootDataset() const;
309 
312  DDS* getDDSForCurrentDataset() const;
313 
321  void pushCurrentDataset(NetcdfElement* dataset);
322 
330  void addChildDatasetToCurrentDataset(NetcdfElement* dataset);
331 
338  void popCurrentDataset(NetcdfElement* dataset);
339 
343  bool parsingDataRequest() const;
344 
348  void resetParseState();
349 
353  void loadLocation(const std::string& location, agg_util::DDSLoader::ResponseType responseType,
354  BESDapResponse* response);
355 
357  bool isNameAlreadyUsedAtCurrentScope(const std::string& name);
358 
366  BaseType* getVariableInCurrentVariableContainer(const string& name);
367 
375  BaseType* getVariableInContainer(const string& varName, BaseType* pContainer);
376 
384  BaseType* getVariableInDDS(const string& varName);
385 
400  void addCopyOfVariableAtCurrentScope(BaseType& varTemplate);
401 
406  void deleteVariableAtCurrentScope(const string& name);
407 
411  BaseType* getCurrentVariable() const;
412 
417  void setCurrentVariable(BaseType* pVar);
418 
425  static bool typeCheckDAPVariable(const BaseType& var, const string& expectedType);
426 
435  AttrTable* getCurrentAttrTable() const;
436 
442  void setCurrentAttrTable(AttrTable* pAT);
443 
448  AttrTable* getGlobalAttrTable() const;
449 
454  bool attributeExistsAtCurrentScope(const string& name) const;
455 
461  bool findAttribute(const string& name, AttrTable::Attr_iter& attr) const;
462 
466  void clearAllAttrTables(DDS* dds);
467 
469  void clearVariableMetadataRecursively(BaseType* var);
470 
476  int tokenizeAttrValues(vector<string>& tokens, const string& values, const string& dapAttrTypeName,
477  const string& separator);
478 
487  int tokenizeValuesForDAPType(vector<string>& tokens, const string& values, AttrType dapType,
488  const string& separator);
489 
491  void enterScope(const string& name, ScopeStack::ScopeType type);
492 
494  void exitScope();
495 
497  void printScope() const;
498 
500  string getScopeString() const;
501 
503  string getTypedScopeString() const;
504 
506  int getScopeDepth() const;
507 
510  void pushElement(NCMLElement* elt);
511 
515  void popElement();
516 
518  NCMLElement* getCurrentElement() const;
519 
522  typedef std::vector<NCMLElement*>::const_reverse_iterator ElementStackConstIterator;
523  ElementStackConstIterator getElementStackBegin() const
524  {
525  return _elementStack.rbegin();
526  }
527  ElementStackConstIterator getElementStackEnd() const
528  {
529  return _elementStack.rend();
530  }
531 
535  void clearElementStack();
536 
538  void processStartNCMLElement(const std::string& name, const XMLAttributeMap& attrs);
539 
541  void processEndNCMLElement(const std::string& name);
542 
546  const DimensionElement* getDimensionAtLexicalScope(const string& dimName) const;
547 
552  string printAllDimensionsAtLexicalScope() const;
553 
567  void enterOtherXMLParsingState(OtherXMLParser* pOtherXMLParser);
568  bool isParsingOtherXML() const;
569 
571  void cleanup();
572 
573 public:
574  // Class Helpers
575 
577  static const string STRUCTURE_TYPE;
578 
590  static string convertNcmlTypeToCanonicalType(const string& ncmlType);
591 
599  void checkDataIsValidForCanonicalTypeOrThrow(const string& type, const vector<string>& tokens) const;
600 
602 private:
603  // 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 };
666 // class NCMLParser
667 
668 }//namespace ncml_module
669 
670 #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:53
ncml_module::ScopeStack::ScopeType
ScopeType
Definition: ScopeStack.h:60
ncml_module::AttributeElement
Concrete class for NcML <attribute> element.
Definition: AttributeElement.h:52
ncml_module::XMLNamespaceStack
Definition: XMLHelpers.h:192
ncml_module::NCMLParser
Definition: NCMLParser.h:158
ncml_module::RemoveElement
Definition: RemoveElement.h:40
ncml_module::AttrTableLazyPtr
Definition: NCMLParser.h:120
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::OtherXMLParser
Definition: OtherXMLParser.h:47
ncml_module::ScanElement
Definition: ScanElement.h:48
ncml_module::ValuesElement
Definition: ValuesElement.h:47
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:61
ncml_module::NCMLElement::Factory
Definition: NCMLElement.h:71
ncml_module::NCMLElement
Base class for NcML element concrete classes.
Definition: NCMLElement.h:61
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:577
ncml_module::XMLNamespaceMap
Definition: XMLHelpers.h:150
ncml_module::SaxParser
Interface class for the wrapper between libxml C SAX parser and our NCMLParser.
Definition: SaxParser.h:48