OPeNDAP Hyrax Back End Server (BES) Updated for version 3.8.3
|
00001 // BESXMLDefineCommand.cc 00002 00003 // This file is part of bes, A C++ back-end server implementation framework 00004 // for the OPeNDAP Data Access Protocol. 00005 00006 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research 00007 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu> 00008 // 00009 // This library is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU Lesser General Public 00011 // License as published by the Free Software Foundation; either 00012 // version 2.1 of the License, or (at your option) any later version. 00013 // 00014 // This library is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 // Lesser General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU Lesser General Public 00020 // License along with this library; if not, write to the Free Software 00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 // 00023 // You can contact University Corporation for Atmospheric Research at 00024 // 3080 Center Green Drive, Boulder, CO 80301 00025 00026 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005 00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR. 00028 // 00029 // Authors: 00030 // pwest Patrick West <pwest@ucar.edu> 00031 // jgarcia Jose Garcia <jgarcia@ucar.edu> 00032 00033 #include "BESXMLDefineCommand.h" 00034 #include "BESContainerStorageList.h" 00035 #include "BESXMLUtils.h" 00036 #include "BESUtil.h" 00037 #include "BESResponseNames.h" 00038 #include "BESDataNames.h" 00039 #include "BESSyntaxUserError.h" 00040 #include "BESDebug.h" 00041 00042 BESXMLDefineCommand::BESXMLDefineCommand( const BESDataHandlerInterface &base_dhi ) 00043 : BESXMLCommand( base_dhi ), 00044 _default_constraint( "" ) 00045 { 00046 } 00047 00065 void 00066 BESXMLDefineCommand::parse_request( xmlNode *node ) 00067 { 00068 string value ; // element value, should not be any 00069 string def_name ; // definition name 00070 string action ; // element name, which is the request action 00071 map<string, string> props ; // element properties. Should contain name 00072 // and optionally space 00073 00074 BESXMLUtils::GetNodeInfo( node, action, value, props ) ; 00075 if( action != DEFINE_RESPONSE_STR ) 00076 { 00077 string err = "The specified command " + action 00078 + " is not a set context command" ; 00079 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ; 00080 } 00081 00082 _dhi.action = DEFINE_RESPONSE ; 00083 00084 def_name = props["name"] ; 00085 if( def_name.empty() ) 00086 { 00087 string err = action + " command: definition name missing" ; 00088 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ; 00089 } 00090 00091 _dhi.data[DEF_NAME] = def_name ; 00092 _str_cmd = (string)"define " + def_name ; 00093 00094 int num_containers = 0 ; 00095 string child_name ; 00096 string child_value ; 00097 props.clear() ; 00098 xmlNode *child_node = 00099 BESXMLUtils::GetFirstChild( node, child_name, child_value, props ) ; 00100 while( child_node ) 00101 { 00102 if( child_name == "constraint" ) 00103 { 00104 // default constraint for all containers 00105 _default_constraint = child_value ; 00106 } 00107 else if( child_name == "container" ) 00108 { 00109 handle_container_element( action, child_node, child_value, props ) ; 00110 num_containers++ ; 00111 } 00112 else if( child_name == "aggregate" ) 00113 { 00114 handle_aggregate_element( action, child_node, child_value, props ) ; 00115 } 00116 00117 // get the next child element 00118 props.clear() ; 00119 child_name.clear() ; 00120 child_value.clear() ; 00121 child_node = BESXMLUtils::GetNextChild( child_node, child_name, 00122 child_value, props ) ; 00123 } 00124 00125 if( num_containers < 1 ) 00126 { 00127 string err = action + "The define element must contain at least " 00128 + "one container element" ; 00129 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ; 00130 } 00131 00132 _str_cmd += " as " ; 00133 bool first = true ; 00134 vector<string>::iterator i = _containers.begin() ; 00135 vector<string>::iterator e = _containers.end() ; 00136 for( ; i != e; i++ ) 00137 { 00138 if( !first ) _str_cmd += "," ; 00139 _str_cmd += (*i) ; 00140 first = false ; 00141 } 00142 if( _constraints.size() ) 00143 { 00144 _str_cmd += " with " ; 00145 first = true ; 00146 map<string,string>::iterator ci = _constraints.begin() ; 00147 map<string,string>::iterator ce = _constraints.end() ; 00148 for( ; ci != ce; ci++ ) 00149 { 00150 if( !first ) _str_cmd += "," ; 00151 _str_cmd += (*ci).first + ".constraint=\"" + (*ci).second + "\"" ; 00152 first = false ; 00153 string attrs = _attributes[(*ci).first] ; 00154 if( !attrs.empty() ) 00155 { 00156 _str_cmd += "," + (*ci).first + ".attributes=\"" + attrs + "\""; 00157 } 00158 } 00159 } 00160 _str_cmd += ";" ; 00161 00162 // now that we've set the action, go get the response handler for the 00163 // action 00164 BESXMLCommand::set_response() ; 00165 } 00166 00181 void 00182 BESXMLDefineCommand::handle_container_element( const string &action, 00183 xmlNode *node, 00184 const string &value, 00185 map<string,string> &props ) 00186 { 00187 string name = props["name"] ; 00188 if( name.empty() ) 00189 { 00190 string err = action + " command: container element missing name prop" ; 00191 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ; 00192 } 00193 00194 _containers.push_back( name ) ; 00195 00196 bool have_constraint = false ; 00197 bool have_attributes = false ; 00198 string child_name ; 00199 string child_value ; 00200 string constraint ; 00201 string attributes ; 00202 map<string,string> child_props ; 00203 xmlNode *child_node = 00204 BESXMLUtils::GetFirstChild( node, child_name, child_value, child_props); 00205 while( child_node ) 00206 { 00207 if( child_name == "constraint" ) 00208 { 00209 if( child_props.size() ) 00210 { 00211 string err = action + " command: constraint element " 00212 + "should not contain properties" ; 00213 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ; 00214 } 00215 if( child_value.empty() ) 00216 { 00217 string err = action + " command: attributes element " 00218 + "missing value" ; 00219 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ; 00220 } 00221 if( have_constraint ) 00222 { 00223 string err = action + " command: container element " 00224 + "contains multiple constraint elements" ; 00225 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ; 00226 } 00227 have_constraint = true ; 00228 _constraints[name] = child_value ; 00229 } 00230 else if( child_name == "attributes" ) 00231 { 00232 if( child_props.size() ) 00233 { 00234 string err = action + " command: attributes element " 00235 + "should not contain properties" ; 00236 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ; 00237 } 00238 if( child_value.empty() ) 00239 { 00240 string err = action + " command: attributes element " 00241 + "missing value" ; 00242 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ; 00243 } 00244 if( have_attributes ) 00245 { 00246 string err = action + " command: container element " 00247 + "contains multiple attributes elements" ; 00248 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ; 00249 } 00250 have_attributes = true ; 00251 _attributes[name] = child_value ; 00252 } 00253 00254 // get the next child element 00255 props.clear() ; 00256 child_name.clear() ; 00257 child_value.clear() ; 00258 child_node = BESXMLUtils::GetNextChild( child_node, child_name, 00259 child_value, props ) ; 00260 } 00261 } 00262 00274 void 00275 BESXMLDefineCommand::handle_aggregate_element( const string &action, 00276 xmlNode *node, 00277 const string &value, 00278 map<string,string> &props ) 00279 { 00280 string handler = props["handler"] ; 00281 string cmd = props["cmd"] ; 00282 if( handler.empty() ) 00283 { 00284 string err = action + " command: must specify aggregation handler" ; 00285 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ; 00286 } 00287 if( cmd.empty() ) 00288 { 00289 string err = action + " command: must specify aggregation cmd" ; 00290 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ; 00291 } 00292 00293 _dhi.data[AGG_HANDLER] = handler ; 00294 _dhi.data[AGG_CMD] = cmd ; 00295 _str_cmd += " aggregate using " + handler + " by " + cmd ; 00296 } 00297 00300 void 00301 BESXMLDefineCommand::prep_request() 00302 { 00303 vector<string>::iterator i = _containers.begin() ; 00304 vector<string>::iterator e = _containers.end() ; 00305 for( ; i != e; i++ ) 00306 { 00307 // look for the specified container 00308 BESContainer *d = 00309 BESContainerStorageList::TheList()->look_for( (*i) ) ; 00310 string constraint = _constraints[(*i)] ; 00311 if( constraint.empty() ) constraint = _default_constraint ; 00312 d->set_constraint( constraint ) ; 00313 d->set_attributes( _attributes[(*i)] ) ; 00314 _dhi.containers.push_back( d ) ; 00315 BESDEBUG( "xml", "define using container: " << endl << *d << endl ) ; 00316 } 00317 } 00318 00325 void 00326 BESXMLDefineCommand::dump( ostream &strm ) const 00327 { 00328 strm << BESIndent::LMarg << "BESXMLDefineCommand::dump - (" 00329 << (void *)this << ")" << endl ; 00330 BESIndent::Indent() ; 00331 BESXMLCommand::dump( strm ) ; 00332 BESIndent::UnIndent() ; 00333 } 00334 00335 BESXMLCommand * 00336 BESXMLDefineCommand::CommandBuilder( const BESDataHandlerInterface &base_dhi ) 00337 { 00338 return new BESXMLDefineCommand( base_dhi ) ; 00339 } 00340