OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
NCMLElement.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 "NCMLDebug.h"
31 #include "NCMLElement.h"
32 #include "NCMLParser.h"
33 
34 // Factory Includes for Concrete Subtypes
35 #include "AggregationElement.h"
36 #include "AttributeElement.h"
37 #include "DimensionElement.h"
38 #include "ExplicitElement.h"
39 #include "NetcdfElement.h"
40 #include "ReadMetadataElement.h"
41 #include "RemoveElement.h"
42 #include "ScanElement.h"
43 #include "ValuesElement.h"
44 #include "VariableAggElement.h"
45 #include "VariableElement.h"
46 
47 using std::string;
48 using std::vector;
49 
50 namespace ncml_module
51 {
52 
54 
56  : _protos()
57  {
58  initialize();
59  }
60 
62  {
63  // Delete all the prototype objects
64  while (!_protos.empty())
65  {
66  const NCMLElement* proto = _protos.back();
67  delete proto;
68  _protos.pop_back();
69  }
70  }
71 
72  void
73  NCMLElement::Factory::addPrototype(const NCMLElement* proto)
74  {
75  VALID_PTR(proto);
76 
77  // If a proto already exists, erase and delete it so we can add the new one.
78  const string& typeName = proto->getTypeName();
79  ProtoList::iterator existingIt = findPrototype(typeName);
80  if (existingIt != _protos.end())
81  {
82  BESDEBUG("ncml", "WARNING: Already got NCMLElement prototype for type=" << typeName << " so replacing with new one." << endl);
83  const NCMLElement* oldOne = *existingIt;
84  _protos.erase(existingIt);
85  delete oldOne;
86  }
87 
88  // Now it's safe to add new one
89  _protos.push_back(proto);
90  }
91 
92  NCMLElement::Factory::ProtoList::iterator
93  NCMLElement::Factory::findPrototype(const std::string& elementTypeName)
94  {
95  ProtoList::iterator it = _protos.end();
96  ProtoList::iterator endIt = _protos.end();
97  for (it = _protos.begin(); it != endIt; ++it)
98  {
99  if ((*it)->getTypeName() == elementTypeName)
100  {
101  return it;
102  }
103  }
104  return endIt;
105  }
106 
107  void
108  NCMLElement::Factory::initialize()
109  {
110  // Enter prototypes for all the concrete subclasses
111  addPrototype(new RemoveElement());
112  addPrototype(new ExplicitElement());
113  addPrototype(new ReadMetadataElement());
114  addPrototype(new NetcdfElement());
115  addPrototype(new AttributeElement());
116  addPrototype(new VariableElement());
117  addPrototype(new ValuesElement());
118  addPrototype(new DimensionElement());
119  addPrototype(new AggregationElement());
120  addPrototype(new VariableAggElement());
121  addPrototype(new ScanElement());
122  }
123 
124 
126  NCMLElement::Factory::makeElement(const string& eltTypeName, const XMLAttributeMap& attrs, NCMLParser& parser)
127  {
128  ProtoList::const_iterator it = findPrototype(eltTypeName);
129  if (it == _protos.end()) // not found
130  {
131  BESDEBUG("ncml", "NCMLElement::Factory cannot find prototype for element type=" << eltTypeName << endl);
132  return RCPtr<NCMLElement>(0);
133  }
134 
135  RCPtr<NCMLElement> newElt = RCPtr<NCMLElement>((*it)->clone());
136  VALID_PTR(newElt.get());
137  // set the parser first if given it since exceptions use it
138  newElt->setParser(&parser);
139  newElt->setAttributes(attrs);
140 
141  return newElt; //relinquish
142  }
143 
145 
146 
148  : RCObject()
149  , _parser(p)
150  {
151  }
152 
154  : RCObjectInterface()
155  , RCObject(proto)
156  , _parser(proto._parser)
157  {
158  }
159 
161  {
162  _parser = 0;
163  }
164 
165  void
167  {
168  // make sure we only call it once when we create it in the parser.
169  NCML_ASSERT_MSG(!_parser, "NCMLElement::setParser() called more than once. Logic bug!");
170  _parser = p;
171  }
172 
173  int
175  {
176  return _parser->getParseLineNumber();
177  }
178 
179  void
180  NCMLElement::handleContent(const string& content)
181  {
182  if (!NCMLUtil::isAllWhitespace(content))
183  {
185  "Got non-whitespace for element content and didn't expect it. Element=" + toString() + " content=\"" +
186  content + "\"");
187  }
188  }
189 
190  bool
192  const vector<string>& validAttrs,
193  vector<string>* pInvalidAttrs /* = 0 */,
194  bool printInvalid /* = true */,
195  bool throwOnError /* = true */)
196  {
197  bool ret = true; // optimism in the face of uncertainty!
198 
199  // Make sure we always have an array to put results in.
200  vector<string> myInvalidAttrs;
201  if (!pInvalidAttrs)
202  {
203  pInvalidAttrs = &myInvalidAttrs;
204  }
205  VALID_PTR(pInvalidAttrs);
206 
207  // Check the lists
208  if (!areAllAttributesValid(attrs, validAttrs, pInvalidAttrs))
209  {
210  // If any is wrong, cons up the list of errors.
211  ret = false;
212 
213  // If we need to print or throw the error cases, then build the list up
214  if (printInvalid || throwOnError)
215  {
216  std::ostringstream oss;
217  oss << "Got invalid attribute for element = " << getTypeName();
218  oss << " The invalid attributes were: {";
219  for (unsigned int i=0; i<pInvalidAttrs->size(); ++i)
220  {
221  oss << (*pInvalidAttrs)[i];
222  if (i < pInvalidAttrs->size()-1) oss << ", ";
223  }
224  oss << "}";
225  if (printInvalid)
226  {
227  BESDEBUG("ncml", oss.str() << endl);
228  }
229  if (throwOnError)
230  {
232  oss.str());
233  }
234  }
235  }
236  return ret;
237  }
238 
239  std::string
240  NCMLElement::printAttributeIfNotEmpty(const std::string& attrName, const std::string& attrValue)
241  {
242  return ( (attrValue.empty())?(""):(" " + attrName + "=\"" + attrValue + "\""));
243  }
244 
245  bool
246  NCMLElement::isValidAttribute(const std::vector<string>& validAttrs, const string& attr)
247  {
248  bool ret = false;
249  for (unsigned int i=0; i<validAttrs.size(); ++i)
250  {
251  if (attr == validAttrs[i])
252  {
253  ret = true;
254  break;
255  }
256  }
257  return ret;
258  }
259 
260  bool
262  const std::vector<string>& validAttrs,
263  std::vector<string>* pInvalidAttributes/*=0*/)
264  {
265  if (pInvalidAttributes)
266  {
267  pInvalidAttributes->resize(0);
268  }
269  bool ret = true;
271  XMLAttributeMap::const_iterator endIt = attrMap.end();
272  for (it = attrMap.begin(); it != endIt; ++it)
273  {
274  const string& attr = it->localname;
275  if (!isValidAttribute(validAttrs, attr))
276  {
277  ret = false;
278  if (pInvalidAttributes)
279  {
280  pInvalidAttributes->push_back(attr);
281  }
282  else
283  {
284  // Early exit only if we don't need the full list of bad ones...
285  break;
286  }
287  }
288  }
289  return ret;
290  }
291 
292 
293 } // namespace ncml_module
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
XMLAttributeMap::const_iterator begin() const
Definition: XMLHelpers.cc:169
static bool areAllAttributesValid(const XMLAttributeMap &attrMap, const std::vector< string > &validAttrs, std::vector< string > *pInvalidAttributes=0)
Definition: NCMLElement.cc:261
An abstract superclass for NCMLArray that handles the non-parameterized functionality and allows u...
static bool isAllWhitespace(const std::string &str)
Is all the string whitespace as defined by chars in WHITESPACE ?
Definition: NCMLUtil.cc:110
#define NCML_ASSERT_MSG(cond, msg)
Definition: NCMLDebug.h:83
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
virtual std::string toString() const =0
Return a string describing the element.
#define THROW_NCML_PARSE_ERROR(parseLine, msg)
Definition: NCMLDebug.h:69
A reference to an RCObject which automatically ref() and deref() on creation and destruction.
Definition: RCObject.h:279
void setParser(NCMLParser *p)
Definition: NCMLElement.cc:166
A base class for a simple reference counted object.
Definition: RCObject.h:162
NCMLElement(NCMLParser *p)
Definition: NCMLElement.cc:147
Base class for NcML element concrete classes.
Definition: NCMLElement.h:64
int line() const
Return the current parse line number.
Definition: NCMLElement.cc:174
virtual const std::string & getTypeName() const =0
Return the type of the element, which should be: the same as ConcreteClassName::getTypeName() ...
virtual void handleContent(const std::string &content)
Handle the characters content for the element.
Definition: NCMLElement.cc:180
XMLAttributeMap::const_iterator end() const
Definition: XMLHelpers.cc:175
RCPtr< NCMLElement > makeElement(const std::string &eltTypeName, const XMLAttributeMap &attrs, NCMLParser &parser)
Create an element of the proper type with the given AttrMap for its defined attributes.
Definition: NCMLElement.cc:126
vector< XMLAttribute >::const_iterator const_iterator
Definition: XMLHelpers.h:104
#define VALID_PTR(ptr)
Definition: NCMLDebug.h:88
T * get() const
Definition: RCObject.h:334
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
static bool isValidAttribute(const std::vector< string > &validAttrs, const string &attr)
Definition: NCMLElement.cc:246