OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
BESXMLDefineCommand.cc
Go to the documentation of this file.
1 // BESXMLDefineCommand.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact University Corporation for Atmospheric Research at
24 // 3080 Center Green Drive, Boulder, CO 80301
25 
26 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 #include "BESXMLDefineCommand.h"
35 #include "BESContainerStorage.h"
36 #include "BESXMLUtils.h"
37 #include "BESUtil.h"
38 #include "BESResponseNames.h"
39 #include "BESDataNames.h"
40 #include "BESSyntaxUserError.h"
41 #include "BESDebug.h"
42 
44  BESXMLCommand(base_dhi), _default_constraint(""), _default_dap4_constraint(""), _default_dap4_function("")
45 {
46 }
47 
66 {
67  string value; // element value, should not be any
68  string def_name; // definition name
69  string def_space; // definition storage space
70  string action; // element name, which is the request action
71  map<string, string> props; // element properties. Should contain name
72  // and optionally space
73 
74  BESXMLUtils::GetNodeInfo(node, action, value, props);
75  if (action != DEFINE_RESPONSE_STR) {
76  string err = "The specified command " + action + " is not a set context command";
77  throw BESSyntaxUserError(err, __FILE__, __LINE__);
78  }
79 
81 
82  def_name = props["name"];
83  if (def_name.empty()) {
84  string err = action + " command: definition name missing";
85  throw BESSyntaxUserError(err, __FILE__, __LINE__);
86  }
87 
88  _dhi.data[DEF_NAME] = def_name;
89  _str_cmd = (string) "define " + def_name;
90 
91  def_space = props["space"];
92  if (!def_space.empty()) {
93  _str_cmd += " in " + def_space;
94  }
95  _dhi.data[STORE_NAME] = def_space;
96 
97  int num_containers = 0;
98  string child_name;
99  string child_value;
100  props.clear();
101  xmlNode *child_node = BESXMLUtils::GetFirstChild(node, child_name, child_value, props);
102  while (child_node) {
103  if (child_name == "constraint") {
104  // default constraint for all containers
105  _default_constraint = child_value;
106  }
107  else if (child_name == "dap4constraint") {
108  // default function for all containers
109  _default_dap4_constraint = child_value;
110  }
111  else if (child_name == "dap4function") {
112  // default function for all containers
113  _default_dap4_function = child_value;
114  }
115  else if (child_name == "container") {
116  handle_container_element(action, child_node, child_value, props);
117  num_containers++;
118  }
119  else if (child_name == "aggregate") {
120  handle_aggregate_element(action, child_node, child_value, props);
121  }
122 
123  // get the next child element
124  props.clear();
125  child_name.clear();
126  child_value.clear();
127  child_node = BESXMLUtils::GetNextChild(child_node, child_name, child_value, props);
128  }
129 
130  if (num_containers < 1) {
131  string err = action + "The define element must contain at least " + "one container element";
132  throw BESSyntaxUserError(err, __FILE__, __LINE__);
133  }
134 
135  _str_cmd += " as ";
136  bool first = true;
137  vector<string>::iterator i = _containers.begin();
138  vector<string>::iterator e = _containers.end();
139  for (; i != e; i++) {
140  if (!first) _str_cmd += ",";
141  _str_cmd += (*i);
142  first = false;
143  }
144 
145  if (_constraints.size() || _dap4constraints.size() || _dap4functions.size() || _attributes.size()) {
146  _str_cmd += " with ";
147  first = true;
148  i = _containers.begin();
149  e = _containers.end();
150  for (; i != e; i++) {
151  if (_constraints.count((*i))) {
152  if (!first) _str_cmd += ",";
153  first = false;
154  _str_cmd += (*i) + ".constraint=\"" + _constraints[(*i)] + "\"";
155  }
156  if (_dap4constraints.count((*i))) {
157  if (!first) _str_cmd += ",";
158  first = false;
159  _str_cmd += (*i) + ".dap4constraint=\"" + _dap4constraints[(*i)] + "\"";
160  }
161  if (_dap4functions.count((*i))) {
162  if (!first) _str_cmd += ",";
163  first = false;
164  _str_cmd += (*i) + ".dap4function=\"" + _dap4functions[(*i)] + "\"";
165  }
166  if (_attributes.count((*i))) {
167  if (!first) _str_cmd += ",";
168  first = false;
169  _str_cmd += (*i) + ".attributes=\"" + _attributes[(*i)] + "\"";
170  }
171  }
172  }
173 
174  _str_cmd += ";";
175 
176  // now that we've set the action, go get the response handler for the
177  // action
179 }
180 
195 void BESXMLDefineCommand::handle_container_element(const string &action, xmlNode *node, const string &/*value*/,
196  map<string, string> &props)
197 {
198  string name = props["name"];
199  if (name.empty()) {
200  string err = action + " command: container element missing name prop";
201  throw BESSyntaxUserError(err, __FILE__, __LINE__);
202  }
203 
204  _containers.push_back(name);
205 
206  string space = props["space"];
207  _stores[name] = space;
208 
209  bool have_constraint = false;
210  bool have_dap4constraint = false;
211  bool have_dap4function = false;
212  bool have_attributes = false;
213  string child_name;
214  string child_value;
215  string constraint;
216  string attributes;
217  map<string, string> child_props;
218  xmlNode *child_node = BESXMLUtils::GetFirstChild(node, child_name, child_value, child_props);
219  while (child_node) {
220  if (child_name == "constraint") {
221  if (child_props.size()) {
222  string err = action + " command: constraint element " + "should not contain properties";
223  throw BESSyntaxUserError(err, __FILE__, __LINE__);
224  }
225  if (child_value.empty()) {
226  string err = action + " command: constraint element " + "missing value";
227  throw BESSyntaxUserError(err, __FILE__, __LINE__);
228  }
229  if (have_constraint) {
230  string err = action + " command: container element " + "contains multiple constraint elements";
231  throw BESSyntaxUserError(err, __FILE__, __LINE__);
232  }
233  have_constraint = true;
234  _constraints[name] = child_value;
235  }
236  else if (child_name == "dap4constraint") {
237  if (child_props.size()) {
238  string err = action + " command: constraint element " + "should not contain properties";
239  throw BESSyntaxUserError(err, __FILE__, __LINE__);
240  }
241  if (child_value.empty()) {
242  string err = action + " command: constraint element " + "missing value";
243  throw BESSyntaxUserError(err, __FILE__, __LINE__);
244  }
245  if (have_dap4constraint) {
246  string err = action + " command: container element " + "contains multiple constraint elements";
247  throw BESSyntaxUserError(err, __FILE__, __LINE__);
248  }
249  have_dap4constraint = true;
250  _dap4constraints[name] = child_value;
251  }
252  else if (child_name == "dap4function") {
253  if (child_props.size()) {
254  string err = action + " command: dap4_function element " + "should not contain properties";
255  throw BESSyntaxUserError(err, __FILE__, __LINE__);
256  }
257  if (child_value.empty()) {
258  string err = action + " command: dap4_function element " + "missing value";
259  throw BESSyntaxUserError(err, __FILE__, __LINE__);
260  }
261  if (have_dap4function) {
262  string err = action + " command: container element " + "contains multiple dap4_function elements";
263  throw BESSyntaxUserError(err, __FILE__, __LINE__);
264  }
265  have_dap4function = true;
266  _dap4functions[name] = child_value;
267  }
268  else if (child_name == "attributes") {
269  if (child_props.size()) {
270  string err = action + " command: attributes element " + "should not contain properties";
271  throw BESSyntaxUserError(err, __FILE__, __LINE__);
272  }
273  if (child_value.empty()) {
274  string err = action + " command: attributes element " + "missing value";
275  throw BESSyntaxUserError(err, __FILE__, __LINE__);
276  }
277  if (have_attributes) {
278  string err = action + " command: container element " + "contains multiple attributes elements";
279  throw BESSyntaxUserError(err, __FILE__, __LINE__);
280  }
281  have_attributes = true;
282  _attributes[name] = child_value;
283  }
284 
285  // get the next child element
286  props.clear();
287  child_name.clear();
288  child_value.clear();
289  child_node = BESXMLUtils::GetNextChild(child_node, child_name, child_value, props);
290  }
291 }
292 
304 void BESXMLDefineCommand::handle_aggregate_element(const string &action, xmlNode */*node*/, const string &/*value*/,
305  map<string, string> &props)
306 {
307  string handler = props["handler"];
308  string cmd = props["cmd"];
309  if (handler.empty()) {
310  string err = action + " command: must specify aggregation handler";
311  throw BESSyntaxUserError(err, __FILE__, __LINE__);
312  }
313  if (cmd.empty()) {
314  string err = action + " command: must specify aggregation cmd";
315  throw BESSyntaxUserError(err, __FILE__, __LINE__);
316  }
317 
318  _dhi.data[AGG_HANDLER] = handler;
319  _dhi.data[AGG_CMD] = cmd;
320  _str_cmd += " aggregate using " + handler + " by " + cmd;
321 }
322 
326 {
327  vector<string>::iterator i = _containers.begin();
328  vector<string>::iterator e = _containers.end();
329  for (; i != e; i++) {
330  // look for the specified container
331  BESContainer *c = 0;
332 
333  // first see if a particular store is being used
334  string store = _stores[(*i)];
335  if (!store.empty()) {
337  if (cs) c = cs->look_for((*i));
338  }
339  else {
341  }
342  if (!c && BESContainerStorageList::TheList()->isnice() == false) {
343  string s = (string) "Could not find the container " + (*i);
344  throw BESSyntaxUserError(s, __FILE__, __LINE__);
345  }
346 
347  // FIXME What use case do we have in which the "default" value of the constraint is not an empty string?
348  string constraint = _constraints[(*i)];
349  if (constraint.empty()) constraint = _default_constraint;
350  c->set_constraint(constraint);
351 
352  // FIXME What use case do we have in which the "default" value of the dap4constraint is not an empty string?
353  string dap4constraint = _dap4constraints[(*i)];
354  if (dap4constraint.empty()) dap4constraint = _default_dap4_constraint;
355  c->set_dap4_constraint(dap4constraint);
356 
357  // FIXME What use case do we have in which the "default" value of the dap4function is not an empty string?
358  string function = _dap4functions[(*i)];
359  if (function.empty()) function = _default_dap4_function;
360  c->set_dap4_function(function);
361 
362  string attrs = _attributes[(*i)];
363  c->set_attributes(attrs);
364  _dhi.containers.push_back(c);
365  BESDEBUG( "xml", "define using container: " << endl << *c << endl );
366  }
367  }
368 
375 void BESXMLDefineCommand::dump(ostream &strm) const
376 {
377  strm << BESIndent::LMarg << "BESXMLDefineCommand::dump - (" << (void *) this << ")" << endl;
379  BESXMLCommand::dump(strm);
381 }
382 
385 {
386  return new BESXMLDefineCommand(base_dhi);
387 }
388 
provides persistent storage for data storage information represented by a container.
#define STORE_NAME
Definition: BESDataNames.h:62
static xmlNode * GetFirstChild(xmlNode *node, string &child_name, string &child_value, map< string, string > &child_props)
get the first element child node for the given node
Definition: BESXMLUtils.cc:145
BESXMLDefineCommand(const BESDataHandlerInterface &base_dhi)
#define DEF_NAME
Definition: BESDataNames.h:68
list< BESContainer * > containers
virtual BESContainerStorage * find_persistence(const string &persist_name)
find the persistence store with the given name
static xmlNode * GetNextChild(xmlNode *child_node, string &next_name, string &next_value, map< string, string > &next_props)
get the next element child node after the given child node
Definition: BESXMLUtils.cc:180
static void GetNodeInfo(xmlNode *node, string &name, string &value, map< string, string > &props)
get the name, value if any, and any properties for the specified node
Definition: BESXMLUtils.cc:105
BESDataHandlerInterface _dhi
Definition: BESXMLCommand.h:57
virtual BESContainer * look_for(const string &sym_name)=0
looks for a container in this persistent store
#define AGG_CMD
Definition: BESDataNames.h:40
static void Indent()
Definition: BESIndent.cc:38
error thrown if there is a user syntax error in the request or any other user error ...
virtual void parse_request(xmlNode *node)
parse a show command.
virtual void set_response()
The request has been parsed, use the command action name to set the response handler.
virtual void prep_request()
prepare the define command by making sure the containers exist
static ostream & LMarg(ostream &strm)
Definition: BESIndent.cc:73
#define DEFINE_RESPONSE
void set_constraint(const string &s)
set the constraint for this container
Definition: BESContainer.h:104
#define AGG_HANDLER
Definition: BESDataNames.h:41
void set_dap4_constraint(const string &s)
set the constraint for this container
Definition: BESContainer.h:113
static BESXMLCommand * CommandBuilder(const BESDataHandlerInterface &base_dhi)
void set_attributes(const string &attrs)
set desired attributes for this container
Definition: BESContainer.h:151
virtual void dump(ostream &strm) const
dumps information about this object
void set_dap4_function(const string &s)
set the constraint for this container
Definition: BESContainer.h:122
Structure storing information used by the BES to handle the request.
virtual BESContainer * look_for(const string &sym_name)
look for the specified container information in the list of persistent stores.
static BESContainerStorageList * TheList()
map< string, string > data
the map of string data that will be required for the current request.
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
A container is something that holds data.
Definition: BESContainer.h:60
static void UnIndent()
Definition: BESIndent.cc:44
string action
the response object requested, e.g.
#define DEFINE_RESPONSE_STR
virtual void dump(ostream &strm) const
dumps information about this object