bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
NCMLParser.h
1
2// 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 <libdap/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
50namespace agg_util {
51class DDSLoader;
52}
53
54namespace libdap {
55class BaseType;
56class DAS;
57class DDS;
58}
59
60class BESDapResponse;
62class BESDDSResponse;
63
64namespace ncml_module {
67class NCMLElement;
68class NetcdfElement;
69class OtherXMLParser;
70}
71
72using namespace libdap;
73
113namespace ncml_module {
114
115// FDecls
116class 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.
120class AttrTableLazyPtr {
121private:
122 // disallow these.
123 AttrTableLazyPtr(const AttrTableLazyPtr&);
124 AttrTableLazyPtr& operator=(const AttrTableLazyPtr&);
125public:
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
149private:
150
151 void loadAndSetAttrTable();
152
153 const NCMLParser& _parser;
154 mutable AttrTable* _pAttrTable;
155 mutable bool _loaded;
156};
157
158class NCMLParser: public SaxParser {
159public:
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
176public:
184
185 virtual ~NCMLParser();
186
187private:
189 NCMLParser(const NCMLParser& from);
190
192 NCMLParser& operator=(const NCMLParser& from);
193
194public:
195
205 std::unique_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
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
248private:
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
573public:
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
602private:
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
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__ */
Holds a DDS object within the BES.
Represents an OPeNDAP DAP response object within the BES.
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
void set(AttrTable *pAT)
AttrTable * get() const
Definition NCMLParser.cc:93
Base class for NcML element concrete classes.
Definition NCMLElement.h:61
virtual void onParseWarning(std::string msg)
virtual void onEndElement(const std::string &name)
const XMLNamespaceStack & getXMLNamespaceStack() const
virtual void onParseError(std::string msg)
int getParseLineNumber() const
virtual void onStartElement(const std::string &name, const XMLAttributeMap &attrs)
static string convertNcmlTypeToCanonicalType(const string &ncmlType)
virtual void onStartElementWithNamespace(const std::string &localname, const std::string &prefix, const std::string &uri, const XMLAttributeMap &attributes, const XMLNamespaceMap &namespaces)
void checkDataIsValidForCanonicalTypeOrThrow(const string &type, const vector< string > &tokens) const
Make sure the given tokens are valid for the listed type. For example, makes sure floats are well for...
void parseInto(const string &ncmlFilename, agg_util::DDSLoader::ResponseType responseType, BESDapResponse *response)
Same as parse, but the response object to parse into is passed down by the caller rather than created...
static const string STRUCTURE_TYPE
Definition NCMLParser.h:577
virtual void onEndElementWithNamespace(const std::string &localname, const std::string &prefix, const std::string &uri)
std::unique_ptr< BESDapResponse > parse(const std::string &ncmlFilename, agg_util::DDSLoader::ResponseType type)
Parse the NcML filename, returning a newly allocated DDS response containing the underlying dataset t...
virtual void onCharacters(const std::string &content)
NCMLParser(agg_util::DDSLoader &loader)
Create a structure that can parse an NCML filename and returned a transformed response of requested t...
virtual void setParseLineNumber(int line)
Concrete class for NcML <netcdf> element.
STL class.
Helper class for temporarily hijacking an existing dhi to load a DDX response for one particular file...
NcML Parser for adding/modifying/removing metadata (attributes) to existing local datasets using NcML...