OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
DimensionElement.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 #include "DimensionElement.h"
30 #include "NCMLDebug.h"
31 #include "NCMLParser.h"
32 #include "NCMLUtil.h"
33 #include "NetcdfElement.h"
34 #include <sstream>
35 
36 using std::string;
37 using std::stringstream;
38 
39 namespace ncml_module
40 {
41  // the parse name of the element
42  const string DimensionElement::_sTypeName = "dimension";
43  const vector<string> DimensionElement::_sValidAttributes = getValidAttributes();
44 
46  : NCMLElement(0)
47  , _length("0")
48  , _orgName("")
49  , _isUnlimited("")
50  , _isShared("")
51  , _isVariableLength("")
52  , _dim()
53  {
54  }
55 
57  : RCObjectInterface()
58  , NCMLElement(proto)
59  , _length(proto._length)
60  , _orgName(proto._orgName)
61  , _isUnlimited(proto._isUnlimited)
62  , _isShared(proto._isShared)
63  , _isVariableLength(proto._isVariableLength)
64  , _dim(proto._dim)
65  {
66  }
67 
69  : NCMLElement(0)
70  , _length("0")
71  , _orgName("")
72  , _isUnlimited("")
73  , _isShared("")
74  , _isVariableLength("")
75  , _dim(dim)
76  {
77  // Set string to match the int size
78  ostringstream oss;
79  oss << dim.size;
80  _length = oss.str();
81  }
82 
84  {
85  }
86 
87  const string& DimensionElement::getTypeName() const
88  {
89  return _sTypeName;
90  }
91 
94  {
95  return new DimensionElement(*this);
96  }
97 
98  void
100  {
101  _dim.name = attrs.getValueForLocalNameOrDefault("name");
102  _length = attrs.getValueForLocalNameOrDefault("length");
103  _orgName = attrs.getValueForLocalNameOrDefault("orgName");
104  _isUnlimited = attrs.getValueForLocalNameOrDefault("isUnlimited");;
105  _isShared = attrs.getValueForLocalNameOrDefault("isShared");;
106  _isVariableLength = attrs.getValueForLocalNameOrDefault("isVariableLength");
107 
108  // First check that we didn't get any typos...
110 
111  // Parse the size etc
112  parseAndCacheDimension();
113 
114  // Final validation for things we implemented
115  validateOrThrow();
116  }
117 
119  {
120  BESDEBUG("ncml", "DimensionElement::handleBegin called...");
121 
122  // Make sure we're placed at a valid parse location.
123  // Direct child of <netcdf> only now since we dont handle <group>
124  if (!_parser->isScopeNetcdf())
125  {
127  "Got dimension element = " + toString() +
128  " at an invalid parse location. Expected it as a direct child of <netcdf> element only." +
129  " scope=" + _parser->getScopeString());
130  }
131 
132  // This will be the scope we're to be added...
133  NetcdfElement* dataset = _parser->getCurrentDataset();
134  VALID_PTR(dataset);
135 
136  // Make sure the name is unique at this parse level or exception.
137  const DimensionElement* pExistingDim = dataset->getDimensionInLocalScope(name());
138  if (pExistingDim)
139  {
141  "Tried at add dimension " + toString() +
142  " but a dimension with name=" + name() +
143  " already exists in this scope=" + _parser->getScopeString());
144  }
145 
146  // The dataset will maintain a strong reference to us while we're needed.
147  dataset->addDimension(this);
148  }
149 
150  void
151  DimensionElement::handleContent(const string& content)
152  {
153  // BESDEBUG("ncml", "DimensionElement::handleContent called...");
154  if (!NCMLUtil::isAllWhitespace(content))
155  {
157  "Got illegal (non-whitespace) content in element " + toString());
158  }
159  }
160 
161  void
163  {
164  // BESDEBUG("ncml", "DimensionElement::handleEnd called...");
165  }
166 
167  string
169  {
170  string ret = "<" + _sTypeName + " ";
172  ret += NCMLElement::printAttributeIfNotEmpty("length", _length);
173  ret += NCMLElement::printAttributeIfNotEmpty("isShared", _isShared);
174  ret += NCMLElement::printAttributeIfNotEmpty("isVariableLength", _isVariableLength);
175  ret += NCMLElement::printAttributeIfNotEmpty("isUnlimited", _isUnlimited);
176  ret += NCMLElement::printAttributeIfNotEmpty("orgName", _orgName);
177  ret += " >";
178  return ret;
179  }
180 
181  bool
183  {
184  return ( (this->name() == rhs.name()) &&
185  (this->getSize() == rhs.getSize()) );
186  }
187 
188  const string&
190  {
191  return _dim.name;
192  }
193 
194  unsigned int
196  {
197  return _dim.size;
198  }
199 
200  unsigned int
202  {
203  return getLengthNumeric();
204  }
205 
206 
209 
210  void
211  DimensionElement::parseAndCacheDimension()
212  {
213  stringstream sis;
214  sis.str(_length);
215  sis >> _dim.size;
216  if (sis.fail())
217  {
219  "Element " + toString() + " failed to parse the length attribute into a proper unsigned int!");
220  }
221 
222  // @TODO set the _dim.isSizeConstant from the isVariableLength, etc once we know how to use them for aggs
223  _dim.isSizeConstant = true;
224 
225  if (_isShared == "true")
226  {
227  _dim.isShared = true;
228  }
229  else if (_isShared == "false")
230  {
231  _dim.isShared = false;
232  }
233  else if (!_isShared.empty())
234  {
236  "dimension@isShared did not have value in {true,false}.");
237  }
238 
239  }
240 
241  void
242  DimensionElement::validateOrThrow()
243  {
244  // Perhaps we want to warn in BESDEBUG rather than error, but I'd rather be explicit for now.
245  if (!_isShared.empty() ||
246  !_isUnlimited.empty() ||
247  !_isVariableLength.empty() ||
248  !_orgName.empty() )
249  {
251  "Dimension element " + toString() + " has unexpected unimplemented attributes. "
252  "This version of the module only handles name and length.");
253  }
254  }
255 
256  vector<string>
257  DimensionElement::getValidAttributes()
258  {
259  vector<string> validAttrs;
260  validAttrs.reserve(10);
261  validAttrs.push_back("name");
262  validAttrs.push_back("length");
263  validAttrs.push_back("isUnlimited");
264  validAttrs.push_back("isVariableLength");
265  validAttrs.push_back("isShared");
266  validAttrs.push_back("orgName");
267  return validAttrs;
268  }
269 }
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
unsigned int size
Definition: Dimension.h:64
virtual void handleBegin()
Handle a begin on this element.
std::string name
Definition: Dimension.h:61
virtual void setAttributes(const XMLAttributeMap &attrs)
Set the attributes of this from the map.
static const vector< string > _sValidAttributes
void addDimension(DimensionElement *dim)
Add the given element to this scope.
An abstract superclass for NCMLArray that handles the non-parameterized functionality and allows u...
const string getValueForLocalNameOrDefault(const string &localname, const string &defVal="") const
If there is an attribute with localname, return its value, else return default.
Definition: XMLHelpers.cc:209
static bool isAllWhitespace(const std::string &str)
Is all the string whitespace as defined by chars in WHITESPACE ?
Definition: NCMLUtil.cc:110
Concrete class for NcML element.
Definition: NetcdfElement.h:63
const DimensionElement * getDimensionInLocalScope(const string &name) const
bool checkDimensionsMatch(const DimensionElement &rhs) const
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
static const string _sTypeName
#define THROW_NCML_PARSE_ERROR(parseLine, msg)
Definition: NCMLDebug.h:69
virtual void handleContent(const string &content)
Handle the characters content for the element.
Struct for holding information about a dimension of data, minimally a name and a cardinality (size)...
Definition: Dimension.h:50
Base class for NcML element concrete classes.
Definition: NCMLElement.h:64
virtual DimensionElement * clone() const
Make and return a copy of this.
virtual void handleEnd()
Handle the closing of this element.
virtual const string & getTypeName() const
Return the type of the element, which should be: the same as ConcreteClassName::getTypeName() ...
#define VALID_PTR(ptr)
Definition: NCMLDebug.h:88
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
virtual string toString() const
Return a string describing the element.
unsigned int getSize() const
unsigned int getLengthNumeric() const
Parsed version of length()
const string & name() const