BESXMLDefineCommand.cc

Go to the documentation of this file.
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 {
00045 }
00046 
00064 void
00065 BESXMLDefineCommand::parse_request( xmlNode *node )
00066 {
00067     string value ;              // element value, should not be any
00068     string def_name ;           // definition name
00069     string action ;             // element name, which is the request action
00070     map<string, string> props ; // element properties. Should contain name
00071                                 // and optionally space
00072 
00073     BESXMLUtils::GetNodeInfo( node, action, value, props ) ;
00074     if( action != DEFINE_RESPONSE_STR )
00075     {
00076         string err = "The specified command " + action
00077                      + " is not a set context command" ;
00078         throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00079     }
00080 
00081     _dhi.action = DEFINE_RESPONSE ;
00082 
00083     def_name = props["name"] ;
00084     if( def_name.empty() )
00085     {
00086         string err = action + " command: definition name missing" ;
00087         throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00088     }
00089 
00090     _dhi.data[DEF_NAME] = def_name ;
00091     _str_cmd = (string)"define " + def_name ;
00092 
00093     int num_containers = 0 ;
00094     string child_name ;
00095     string child_value ;
00096     props.clear() ;
00097     xmlNode *child_node =
00098         BESXMLUtils::GetFirstChild( node, child_name, child_value, props ) ;
00099     while( child_node )
00100     {
00101         if( child_name == "container" )
00102         {
00103             handle_container_element( action, child_node, child_value, props ) ;
00104             num_containers++ ;
00105         }
00106         else if( child_name == "aggregate" )
00107         {
00108             handle_aggregate_element( action, child_node, child_value, props ) ;
00109         }
00110 
00111         // get the next child element
00112         props.clear() ;
00113         child_name.clear() ;
00114         child_value.clear() ;
00115         child_node = BESXMLUtils::GetNextChild( child_node, child_name,
00116                                                 child_value, props ) ;
00117     }
00118 
00119     if( num_containers < 1 )
00120     {
00121         string err = action + "The define element must contain at least "
00122                      + "one container element" ;
00123         throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00124     }
00125 
00126     _str_cmd += " as " ;
00127     bool first = true ;
00128     vector<string>::iterator i = _containers.begin() ;
00129     vector<string>::iterator e = _containers.end() ;
00130     for( ; i != e; i++ )
00131     {
00132         if( !first ) _str_cmd += "," ;
00133         _str_cmd += (*i) ;
00134         first = false ;
00135     }
00136     if( _constraints.size() )
00137     {
00138         _str_cmd += " with " ;
00139         first = true ;
00140         map<string,string>::iterator ci = _constraints.begin() ;
00141         map<string,string>::iterator ce = _constraints.end() ;
00142         for( ; ci != ce; ci++ )
00143         {
00144             if( !first ) _str_cmd += "," ;
00145             _str_cmd += (*ci).first + ".constraint=\"" + (*ci).second + "\"" ;
00146             first = false ;
00147             string attrs = _attributes[(*ci).first] ;
00148             if( !attrs.empty() )
00149             {
00150                 _str_cmd += "," + (*ci).first + ".attributes=\"" + attrs + "\"";
00151             }
00152         }
00153     }
00154     _str_cmd += ";" ;
00155 
00156     // now that we've set the action, go get the response handler for the
00157     // action
00158     BESXMLCommand::set_response() ;
00159 }
00160 
00175 void
00176 BESXMLDefineCommand::handle_container_element( const string &action,
00177                                                xmlNode *node,
00178                                                const string &value,
00179                                                map<string,string> &props )
00180 {
00181     string name = props["name"] ;
00182     if( name.empty() )
00183     {
00184         string err = action + " command: container element missing name prop" ;
00185         throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00186     }
00187 
00188     _containers.push_back( name ) ;
00189 
00190     bool have_constraint = false ;
00191     bool have_attributes = false ;
00192     string child_name ;
00193     string child_value ;
00194     string constraint ;
00195     string attributes ;
00196     map<string,string> child_props ;
00197     xmlNode *child_node =
00198         BESXMLUtils::GetFirstChild( node, child_name, child_value, child_props);
00199     while( child_node )
00200     {
00201         if( child_name == "constraint" )
00202         {
00203             if( child_props.size() )
00204             {
00205                 string err = action + " command: constraint element "
00206                                     + "should not contain properties" ;
00207                 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00208             }
00209             if( child_value.empty() )
00210             {
00211                 string err = action + " command: attributes element "
00212                                     + "missing value" ;
00213                 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00214             }
00215             if( have_constraint )
00216             {
00217                 string err = action + " command: container element "
00218                                     + "contains multiple constraint elements" ;
00219                 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00220             }
00221             have_constraint = true ;
00222             _constraints[name] = child_value ;
00223         }
00224         else if( child_name == "attributes" )
00225         {
00226             if( child_props.size() )
00227             {
00228                 string err = action + " command: attributes element "
00229                                     + "should not contain properties" ;
00230                 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00231             }
00232             if( child_value.empty() )
00233             {
00234                 string err = action + " command: attributes element "
00235                                     + "missing value" ;
00236                 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00237             }
00238             if( have_attributes )
00239             {
00240                 string err = action + " command: container element "
00241                                     + "contains multiple attributes elements" ;
00242                 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00243             }
00244             have_attributes = true ;
00245             _attributes[name] = child_value ;
00246         }
00247 
00248         // get the next child element
00249         props.clear() ;
00250         child_name.clear() ;
00251         child_value.clear() ;
00252         child_node = BESXMLUtils::GetNextChild( child_node, child_name,
00253                                                 child_value, props ) ;
00254     }
00255 }
00256 
00268 void
00269 BESXMLDefineCommand::handle_aggregate_element( const string &action,
00270                                                xmlNode *node,
00271                                                const string &value,
00272                                                map<string,string> &props )
00273 {
00274     string handler = props["handler"] ;
00275     string cmd = props["cmd"] ;
00276     if( handler.empty() )
00277     {
00278         string err = action + " command: must specify aggregation handler" ;
00279         throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00280     }
00281     if( cmd.empty() )
00282     {
00283         string err = action + " command: must specify aggregation cmd" ;
00284         throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00285     }
00286 
00287     _dhi.data[AGG_HANDLER] = handler ;
00288     _dhi.data[AGG_CMD] = cmd ;
00289     _str_cmd += " aggregate using " + handler + " by " + cmd ;
00290 }
00291 
00294 void
00295 BESXMLDefineCommand::prep_request()
00296 {
00297     vector<string>::iterator i = _containers.begin() ;
00298     vector<string>::iterator e = _containers.end() ;
00299     for( ; i != e; i++ )
00300     {
00301         // look for the specified container
00302         BESContainer *d =
00303             BESContainerStorageList::TheList()->look_for( (*i) ) ;
00304         d->set_constraint( _constraints[(*i)] ) ;
00305         d->set_attributes( _attributes[(*i)] ) ;
00306         _dhi.containers.push_back( d ) ;
00307     }
00308 }
00309 
00316 void
00317 BESXMLDefineCommand::dump( ostream &strm ) const
00318 {
00319     strm << BESIndent::LMarg << "BESXMLDefineCommand::dump - ("
00320                              << (void *)this << ")" << endl ;
00321     BESIndent::Indent() ;
00322     BESXMLCommand::dump( strm ) ;
00323     BESIndent::UnIndent() ;
00324 }
00325 
00326 BESXMLCommand *
00327 BESXMLDefineCommand::CommandBuilder( const BESDataHandlerInterface &base_dhi )
00328 {
00329     return new BESXMLDefineCommand( base_dhi ) ;
00330 }
00331 

Generated on Tue May 11 20:02:06 2010 for OPeNDAP Hyrax Back End Server (BES) by  doxygen 1.4.7