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 
00155     // now that we've set the action, go get the response handler for the
00156     // action
00157     BESXMLCommand::set_response() ;
00158 }
00159 
00174 void
00175 BESXMLDefineCommand::handle_container_element( const string &action,
00176                                                xmlNode *node,
00177                                                const string &value,
00178                                                map<string,string> &props )
00179 {
00180     string name = props["name"] ;
00181     if( name.empty() )
00182     {
00183         string err = action + " command: container element missing name prop" ;
00184         throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00185     }
00186 
00187     _containers.push_back( name ) ;
00188 
00189     bool have_constraint = false ;
00190     bool have_attributes = false ;
00191     string child_name ;
00192     string child_value ;
00193     string constraint ;
00194     string attributes ;
00195     map<string,string> child_props ;
00196     xmlNode *child_node =
00197         BESXMLUtils::GetFirstChild( node, child_name, child_value, child_props);
00198     while( child_node )
00199     {
00200         if( child_name == "constraint" )
00201         {
00202             if( child_props.size() )
00203             {
00204                 string err = action + " command: constraint element "
00205                                     + "should not contain properties" ;
00206                 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00207             }
00208             if( child_value.empty() )
00209             {
00210                 string err = action + " command: attributes element "
00211                                     + "missing value" ;
00212                 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00213             }
00214             if( have_constraint )
00215             {
00216                 string err = action + " command: container element "
00217                                     + "contains multiple constraint elements" ;
00218                 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00219             }
00220             have_constraint = true ;
00221             _constraints[name] = child_value ;
00222         }
00223         else if( child_name == "attributes" )
00224         {
00225             if( child_props.size() )
00226             {
00227                 string err = action + " command: attributes element "
00228                                     + "should not contain properties" ;
00229                 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00230             }
00231             if( child_value.empty() )
00232             {
00233                 string err = action + " command: attributes element "
00234                                     + "missing value" ;
00235                 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00236             }
00237             if( have_attributes )
00238             {
00239                 string err = action + " command: container element "
00240                                     + "contains multiple attributes elements" ;
00241                 throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00242             }
00243             have_attributes = true ;
00244             _attributes[name] = child_value ;
00245         }
00246 
00247         // get the next child element
00248         props.clear() ;
00249         child_name.clear() ;
00250         child_value.clear() ;
00251         child_node = BESXMLUtils::GetNextChild( child_node, child_name,
00252                                                 child_value, props ) ;
00253     }
00254 }
00255 
00267 void
00268 BESXMLDefineCommand::handle_aggregate_element( const string &action,
00269                                                xmlNode *node,
00270                                                const string &value,
00271                                                map<string,string> &props )
00272 {
00273     string handler = props["handler"] ;
00274     string cmd = props["cmd"] ;
00275     if( handler.empty() )
00276     {
00277         string err = action + " command: must specify aggregation handler" ;
00278         throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00279     }
00280     if( cmd.empty() )
00281     {
00282         string err = action + " command: must specify aggregation cmd" ;
00283         throw BESSyntaxUserError( err, __FILE__, __LINE__ ) ;
00284     }
00285 
00286     _dhi.data[AGG_HANDLER] = handler ;
00287     _dhi.data[AGG_CMD] = cmd ;
00288     _str_cmd += " aggregate using " + handler + " by " + cmd ;
00289 }
00290 
00293 void
00294 BESXMLDefineCommand::prep_request()
00295 {
00296     vector<string>::iterator i = _containers.begin() ;
00297     vector<string>::iterator e = _containers.end() ;
00298     for( ; i != e; i++ )
00299     {
00300         // look for the specified container
00301         BESContainer *d =
00302             BESContainerStorageList::TheList()->look_for( (*i) ) ;
00303         d->set_constraint( _constraints[(*i)] ) ;
00304         d->set_attributes( _attributes[(*i)] ) ;
00305         _dhi.containers.push_back( d ) ;
00306     }
00307 }
00308 
00315 void
00316 BESXMLDefineCommand::dump( ostream &strm ) const
00317 {
00318     strm << BESIndent::LMarg << "BESXMLDefineCommand::dump - ("
00319                              << (void *)this << ")" << endl ;
00320     BESIndent::Indent() ;
00321     BESXMLCommand::dump( strm ) ;
00322     BESIndent::UnIndent() ;
00323 }
00324 
00325 BESXMLCommand *
00326 BESXMLDefineCommand::CommandBuilder( const BESDataHandlerInterface &base_dhi )
00327 {
00328     return new BESXMLDefineCommand( base_dhi ) ;
00329 }
00330 

Generated on 27 Oct 2009 for OPeNDAP Hyrax Back End Server (BES) by  doxygen 1.6.1