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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 "BESXMLUtils.h"
36 #include "BESUtil.h"
37 #include "BESResponseNames.h"
38 #include "BESDataNames.h"
39 #include "BESSyntaxUserError.h"
40 #include "BESDebug.h"
41 
43  : BESXMLCommand( base_dhi ),
44  _default_constraint( "" )
45 {
46 }
47 
65 void
67 {
68  string value ; // element value, should not be any
69  string def_name ; // definition name
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  {
77  string err = "The specified command " + action
78  + " is not a set context command" ;
79  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
80  }
81 
83 
84  def_name = props["name"] ;
85  if( def_name.empty() )
86  {
87  string err = action + " command: definition name missing" ;
88  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
89  }
90 
91  _dhi.data[DEF_NAME] = def_name ;
92  _str_cmd = (string)"define " + def_name ;
93 
94  int num_containers = 0 ;
95  string child_name ;
96  string child_value ;
97  props.clear() ;
98  xmlNode *child_node =
99  BESXMLUtils::GetFirstChild( node, child_name, child_value, props ) ;
100  while( child_node )
101  {
102  if( child_name == "constraint" )
103  {
104  // default constraint for all containers
105  _default_constraint = child_value ;
106  }
107  else if( child_name == "container" )
108  {
109  handle_container_element( action, child_node, child_value, props ) ;
110  num_containers++ ;
111  }
112  else if( child_name == "aggregate" )
113  {
114  handle_aggregate_element( action, child_node, child_value, props ) ;
115  }
116 
117  // get the next child element
118  props.clear() ;
119  child_name.clear() ;
120  child_value.clear() ;
121  child_node = BESXMLUtils::GetNextChild( child_node, child_name,
122  child_value, props ) ;
123  }
124 
125  if( num_containers < 1 )
126  {
127  string err = action + "The define element must contain at least "
128  + "one container element" ;
129  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
130  }
131 
132  _str_cmd += " as " ;
133  bool first = true ;
134  vector<string>::iterator i = _containers.begin() ;
135  vector<string>::iterator e = _containers.end() ;
136  for( ; i != e; i++ )
137  {
138  if( !first ) _str_cmd += "," ;
139  _str_cmd += (*i) ;
140  first = false ;
141  }
142  if( _constraints.size() )
143  {
144  _str_cmd += " with " ;
145  first = true ;
146  map<string,string>::iterator ci = _constraints.begin() ;
147  map<string,string>::iterator ce = _constraints.end() ;
148  for( ; ci != ce; ci++ )
149  {
150  if( !first ) _str_cmd += "," ;
151  _str_cmd += (*ci).first + ".constraint=\"" + (*ci).second + "\"" ;
152  first = false ;
153  string attrs = _attributes[(*ci).first] ;
154  if( !attrs.empty() )
155  {
156  _str_cmd += "," + (*ci).first + ".attributes=\"" + attrs + "\"";
157  }
158  }
159  }
160  _str_cmd += ";" ;
161 
162  // now that we've set the action, go get the response handler for the
163  // action
165 }
166 
181 void
182 BESXMLDefineCommand::handle_container_element( const string &action,
183  xmlNode *node,
184  const string &value,
185  map<string,string> &props )
186 {
187  string name = props["name"] ;
188  if( name.empty() )
189  {
190  string err = action + " command: container element missing name prop" ;
191  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
192  }
193 
194  _containers.push_back( name ) ;
195 
196  bool have_constraint = false ;
197  bool have_attributes = false ;
198  string child_name ;
199  string child_value ;
200  string constraint ;
201  string attributes ;
202  map<string,string> child_props ;
203  xmlNode *child_node =
204  BESXMLUtils::GetFirstChild( node, child_name, child_value, child_props);
205  while( child_node )
206  {
207  if( child_name == "constraint" )
208  {
209  if( child_props.size() )
210  {
211  string err = action + " command: constraint element "
212  + "should not contain properties" ;
213  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
214  }
215  if( child_value.empty() )
216  {
217  string err = action + " command: attributes element "
218  + "missing value" ;
219  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
220  }
221  if( have_constraint )
222  {
223  string err = action + " command: container element "
224  + "contains multiple constraint elements" ;
225  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
226  }
227  have_constraint = true ;
228  _constraints[name] = child_value ;
229  }
230  else if( child_name == "attributes" )
231  {
232  if( child_props.size() )
233  {
234  string err = action + " command: attributes element "
235  + "should not contain properties" ;
236  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
237  }
238  if( child_value.empty() )
239  {
240  string err = action + " command: attributes element "
241  + "missing value" ;
242  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
243  }
244  if( have_attributes )
245  {
246  string err = action + " command: container element "
247  + "contains multiple attributes elements" ;
248  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
249  }
250  have_attributes = true ;
251  _attributes[name] = child_value ;
252  }
253 
254  // get the next child element
255  props.clear() ;
256  child_name.clear() ;
257  child_value.clear() ;
258  child_node = BESXMLUtils::GetNextChild( child_node, child_name,
259  child_value, props ) ;
260  }
261 }
262 
274 void
275 BESXMLDefineCommand::handle_aggregate_element( const string &action,
276  xmlNode *node,
277  const string &value,
278  map<string,string> &props )
279 {
280  string handler = props["handler"] ;
281  string cmd = props["cmd"] ;
282  if( handler.empty() )
283  {
284  string err = action + " command: must specify aggregation handler" ;
285  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
286  }
287  if( cmd.empty() )
288  {
289  string err = action + " command: must specify aggregation cmd" ;
290  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
291  }
292 
293  _dhi.data[AGG_HANDLER] = handler ;
294  _dhi.data[AGG_CMD] = cmd ;
295  _str_cmd += " aggregate using " + handler + " by " + cmd ;
296 }
297 
300 void
302 {
303  vector<string>::iterator i = _containers.begin() ;
304  vector<string>::iterator e = _containers.end() ;
305  for( ; i != e; i++ )
306  {
307  // look for the specified container
308  BESContainer *d =
310  string constraint = _constraints[(*i)] ;
311  if( constraint.empty() ) constraint = _default_constraint ;
312  d->set_constraint( constraint ) ;
313  d->set_attributes( _attributes[(*i)] ) ;
314  _dhi.containers.push_back( d ) ;
315  BESDEBUG( "xml", "define using container: " << endl << *d << endl ) ;
316  }
317 }
318 
325 void
326 BESXMLDefineCommand::dump( ostream &strm ) const
327 {
328  strm << BESIndent::LMarg << "BESXMLDefineCommand::dump - ("
329  << (void *)this << ")" << endl ;
331  BESXMLCommand::dump( strm ) ;
333 }
334 
337 {
338  return new BESXMLDefineCommand( base_dhi ) ;
339 }
340 
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
virtual void dump(ostream &strm) const
dumps information about this object
BESXMLDefineCommand(const BESDataHandlerInterface &base_dhi)
virtual void dump(ostream &strm) const
dumps information about this object
#define DEF_NAME
Definition: BESDataNames.h:60
list< BESContainer * > containers
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
#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:102
#define AGG_HANDLER
Definition: BESDataNames.h:41
static BESXMLCommand * CommandBuilder(const BESDataHandlerInterface &base_dhi)
void set_attributes(const string &attrs)
set desired attributes for this container
Definition: BESContainer.h:131
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