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 "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 ),
45  _default_constraint( "" )
46 {
47 }
48 
66 void
68 {
69  string value ; // element value, should not be any
70  string def_name ; // definition name
71  string def_space ; // definition storage space
72  string action ; // element name, which is the request action
73  map<string, string> props ; // element properties. Should contain name
74  // and optionally space
75 
76  BESXMLUtils::GetNodeInfo( node, action, value, props ) ;
77  if( action != DEFINE_RESPONSE_STR )
78  {
79  string err = "The specified command " + action
80  + " is not a set context command" ;
81  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
82  }
83 
85 
86  def_name = props["name"] ;
87  if( def_name.empty() )
88  {
89  string err = action + " command: definition name missing" ;
90  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
91  }
92 
93  _dhi.data[DEF_NAME] = def_name ;
94  _str_cmd = (string)"define " + def_name ;
95 
96  def_space = props["space"] ;
97  if( !def_space.empty() )
98  {
99  _str_cmd += " in " + def_space ;
100  }
101  _dhi.data[STORE_NAME] = def_space ;
102 
103  int num_containers = 0 ;
104  string child_name ;
105  string child_value ;
106  props.clear() ;
107  xmlNode *child_node =
108  BESXMLUtils::GetFirstChild( node, child_name, child_value, props ) ;
109  while( child_node )
110  {
111  if( child_name == "constraint" )
112  {
113  // default constraint for all containers
114  _default_constraint = child_value ;
115  }
116  else if( child_name == "container" )
117  {
118  handle_container_element( action, child_node, child_value, props ) ;
119  num_containers++ ;
120  }
121  else if( child_name == "aggregate" )
122  {
123  handle_aggregate_element( action, child_node, child_value, props ) ;
124  }
125 
126  // get the next child element
127  props.clear() ;
128  child_name.clear() ;
129  child_value.clear() ;
130  child_node = BESXMLUtils::GetNextChild( child_node, child_name,
131  child_value, props ) ;
132  }
133 
134  if( num_containers < 1 )
135  {
136  string err = action + "The define element must contain at least "
137  + "one container element" ;
138  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
139  }
140 
141  _str_cmd += " as " ;
142  bool first = true ;
143  vector<string>::iterator i = _containers.begin() ;
144  vector<string>::iterator e = _containers.end() ;
145  for( ; i != e; i++ )
146  {
147  if( !first ) _str_cmd += "," ;
148  _str_cmd += (*i) ;
149  first = false ;
150  }
151  if( _constraints.size() )
152  {
153  _str_cmd += " with " ;
154  first = true ;
155  map<string,string>::iterator ci = _constraints.begin() ;
156  map<string,string>::iterator ce = _constraints.end() ;
157  for( ; ci != ce; ci++ )
158  {
159  if( !first ) _str_cmd += "," ;
160  _str_cmd += (*ci).first + ".constraint=\"" + (*ci).second + "\"" ;
161  first = false ;
162  string attrs = _attributes[(*ci).first] ;
163  if( !attrs.empty() )
164  {
165  _str_cmd += "," + (*ci).first + ".attributes=\"" + attrs + "\"";
166  }
167  }
168  }
169  _str_cmd += ";" ;
170 
171  // now that we've set the action, go get the response handler for the
172  // action
174 }
175 
190 void
191 BESXMLDefineCommand::handle_container_element( const string &action,
192  xmlNode *node,
193  const string &value,
194  map<string,string> &props )
195 {
196  string name = props["name"] ;
197  if( name.empty() )
198  {
199  string err = action + " command: container element missing name prop" ;
200  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
201  }
202 
203  _containers.push_back( name ) ;
204 
205  string space = props["space"] ;
206  _stores[name] = space ;
207 
208  bool have_constraint = false ;
209  bool have_attributes = false ;
210  string child_name ;
211  string child_value ;
212  string constraint ;
213  string attributes ;
214  map<string,string> child_props ;
215  xmlNode *child_node =
216  BESXMLUtils::GetFirstChild( node, child_name, child_value, child_props);
217  while( child_node )
218  {
219  if( child_name == "constraint" )
220  {
221  if( child_props.size() )
222  {
223  string err = action + " command: constraint element "
224  + "should not contain properties" ;
225  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
226  }
227  if( child_value.empty() )
228  {
229  string err = action + " command: attributes element "
230  + "missing value" ;
231  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
232  }
233  if( have_constraint )
234  {
235  string err = action + " command: container element "
236  + "contains multiple constraint elements" ;
237  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
238  }
239  have_constraint = true ;
240  _constraints[name] = child_value ;
241  }
242  else if( child_name == "attributes" )
243  {
244  if( child_props.size() )
245  {
246  string err = action + " command: attributes element "
247  + "should not contain properties" ;
248  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
249  }
250  if( child_value.empty() )
251  {
252  string err = action + " command: attributes element "
253  + "missing value" ;
254  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
255  }
256  if( have_attributes )
257  {
258  string err = action + " command: container element "
259  + "contains multiple attributes elements" ;
260  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
261  }
262  have_attributes = true ;
263  _attributes[name] = child_value ;
264  }
265 
266  // get the next child element
267  props.clear() ;
268  child_name.clear() ;
269  child_value.clear() ;
270  child_node = BESXMLUtils::GetNextChild( child_node, child_name,
271  child_value, props ) ;
272  }
273 }
274 
286 void
287 BESXMLDefineCommand::handle_aggregate_element( const string &action,
288  xmlNode *node,
289  const string &value,
290  map<string,string> &props )
291 {
292  string handler = props["handler"] ;
293  string cmd = props["cmd"] ;
294  if( handler.empty() )
295  {
296  string err = action + " command: must specify aggregation handler" ;
297  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
298  }
299  if( cmd.empty() )
300  {
301  string err = action + " command: must specify aggregation cmd" ;
302  throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
303  }
304 
305  _dhi.data[AGG_HANDLER] = handler ;
306  _dhi.data[AGG_CMD] = cmd ;
307  _str_cmd += " aggregate using " + handler + " by " + cmd ;
308 }
309 
312 void
314 {
315  vector<string>::iterator i = _containers.begin() ;
316  vector<string>::iterator e = _containers.end() ;
317  for( ; i != e; i++ )
318  {
319  // look for the specified container
320  BESContainer *c = 0 ;
321 
322  // first see if a particilar store is being used
323  string store = _stores[(*i)] ;
324  if( !store.empty() )
325  {
326  BESContainerStorage *cs =
328  if( cs ) c = cs->look_for( (*i) ) ;
329  }
330  else
331  {
333  }
334  if( !c && BESContainerStorageList::TheList()->isnice() == false )
335  {
336  string s = (string)"Could not find the container "
337  + (*i) ;
338  throw BESSyntaxUserError( s, __FILE__, __LINE__ ) ;
339  }
340 
341  string constraint = _constraints[(*i)] ;
342  string attrs = _attributes[(*i)] ;
343  if( constraint.empty() ) constraint = _default_constraint ;
344  c->set_constraint( constraint ) ;
345  c->set_attributes( attrs ) ;
346  _dhi.containers.push_back( c ) ;
347  BESDEBUG( "xml", "define using container: " << endl << *c << endl ) ;
348  }
349 }
350 
357 void
358 BESXMLDefineCommand::dump( ostream &strm ) const
359 {
360  strm << BESIndent::LMarg << "BESXMLDefineCommand::dump - ("
361  << (void *)this << ")" << endl ;
363  BESXMLCommand::dump( strm ) ;
365 }
366 
369 {
370  return new BESXMLDefineCommand( base_dhi ) ;
371 }
372 
provides persistent storage for data storage information represented by a container.
#define STORE_NAME
Definition: BESDataNames.h:54
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:60
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: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
virtual void dump(ostream &strm) const
dumps information about this object
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