CmdPretty.cc

Go to the documentation of this file.
00001 // CmdPretty.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 <libxml/encoding.h>
00034 
00035 #include <iostream>
00036 #include <map>
00037 
00038 using std::cout ;
00039 using std::endl ;
00040 using std::map ;
00041 
00042 #include "CmdPretty.h"
00043 #include "BESXMLUtils.h"
00044 
00045 string CmdPretty::_indent ;
00046 
00047 void
00048 CmdPretty::make_pretty( const string &response, ostream &strm )
00049 {
00050     if( response[0] == '<' && response[1] == '?' )
00051     {
00052         LIBXML_TEST_VERSION
00053 
00054         xmlDoc *doc = NULL ;
00055         xmlNode *root_element = NULL ;
00056 
00057         doc = xmlParseDoc( (unsigned char *)response.c_str() ) ;
00058         if( doc == NULL )
00059         {
00060             cout << "bescmdln tried to pretty print xml document: "
00061                  << "failed to parse document" << endl ;
00062             strm << response ;
00063             xmlCleanupParser() ;
00064             return ;
00065         }
00066 
00067         // get the root element
00068         root_element = xmlDocGetRootElement( doc ) ;
00069         if( !root_element )
00070         {
00071             cout << "bescmdln tried to pretty print xml document: "
00072                  << "failed to get document root" << endl ;
00073             strm << response ;
00074             if( doc ) xmlFreeDoc( doc ) ;
00075             xmlCleanupParser() ;
00076             return ;
00077         }
00078 
00079         CmdPretty::pretty_element( root_element, strm ) ;
00080 
00081         if( doc ) xmlFreeDoc( doc ) ;
00082         xmlCleanupParser() ;
00083     }
00084     else
00085     {
00086         strm << response ;
00087     }
00088 }
00089 
00090 void
00091 CmdPretty::pretty_element( xmlNode *node, ostream &strm )
00092 {
00093     if( !node )
00094     {
00095         return ;
00096     }
00097 
00098     string node_name ;
00099     string node_val ;
00100     map< string, string> node_props ;
00101     BESXMLUtils::GetNodeInfo( node, node_name, node_val, node_props ) ;
00102     pretty_name( node, node_name, strm ) ;
00103     map<string,string>::const_iterator i = node_props.begin() ;
00104     map<string,string>::const_iterator e = node_props.end() ;
00105     for( ; i != e; i++ )
00106     {
00107         strm << " " << (*i).first ;
00108         if( !(*i).second.empty() )
00109         {
00110             strm << "=\"" << (*i).second << "\"" ;
00111         }
00112     }
00113 
00114     string cname ;
00115     string cval ;
00116     map<string, string> cprops ;
00117 
00118     // ok ... bad variable name. This means that the node either has a value
00119     // or has children. So it has stuff.
00120     bool has_stuff = false ;
00121     xmlNode *cnode = BESXMLUtils::GetFirstChild( node, cname, cval, cprops ) ;
00122     
00123     if( !cnode && !node_val.empty() && node_val.length() < 80-_indent.length() )
00124     {
00125         strm << ">" << node_val << "</" << node_name << ">" << endl ;
00126     }
00127     else
00128     {
00129         if( cnode || !node_val.empty() )
00130         {
00131             has_stuff = true ;
00132             strm << ">" << endl ;
00133             CmdPretty::indent( 4 ) ;
00134         }
00135         if( !node_val.empty() )
00136         {
00137             CmdPretty::pretty_value( node_val, strm ) ;
00138         }
00139         while( cnode )
00140         {
00141             CmdPretty::pretty_element( cnode, strm ) ;
00142             cnode = BESXMLUtils::GetNextChild( cnode, cname, cval, cprops ) ;
00143         }
00144         if( has_stuff )
00145         {
00146             CmdPretty::unindent( 4 ) ;
00147             strm << _indent << "</" << node_name << ">" << endl ;
00148         }
00149         else
00150         {
00151             strm << " />" << endl ;
00152         }
00153     }
00154 }
00155 
00156 void
00157 CmdPretty::pretty_value( string &value, ostream &strm )
00158 {
00159     strm << _indent << value << endl ;
00160 }
00161 
00162 void
00163 CmdPretty::pretty_name( xmlNode *node, const string &name, ostream &strm )
00164 {
00165     if( node )
00166     {
00167         // first let's build the node name and display it
00168         xmlNs *ns = node->nsDef ;
00169         string newname ;
00170         bool firstns = true ;
00171         while( ns )
00172         {
00173             if( ns->prefix )
00174             {
00175                 if( !firstns )
00176                 {
00177                     newname += ":" ;
00178                 }
00179                 newname += (const char *)ns->prefix ;
00180             }
00181             ns = ns->next ;
00182             firstns = false ;
00183         }
00184         if( !newname.empty() )
00185         {
00186             newname += ":" ;
00187         }
00188         newname += name ;
00189 
00190         strm << CmdPretty::_indent << "<" << newname ;
00191 
00192         // now let's add the namespace definitions
00193         ns = node->nsDef ;
00194         while( ns )
00195         {
00196             strm << " xmlns" ;
00197             if( ns->prefix )
00198             {
00199                 strm << ":" << ns->prefix ;
00200             }
00201             if( ns->href )
00202             {
00203                 strm << "=\"" << ns->href << "\"" ;
00204             }
00205             ns = ns->next ;
00206         }
00207     }
00208 }
00209 
00210 void
00211 CmdPretty::indent( unsigned int spaces )
00212 {
00213     unsigned int index = 0 ;
00214     for( index = 0; index < spaces; index++ )
00215     {
00216         CmdPretty::_indent += " " ;
00217     }
00218 }
00219 
00220 void
00221 CmdPretty::unindent( unsigned int spaces )
00222 {
00223     if( spaces >= _indent.length() )
00224     {
00225         _indent = "" ;
00226     }
00227     else
00228     {
00229         _indent = _indent.substr( 0, _indent.length() - spaces ) ;
00230     }
00231 }
00232 

Generated on 18 Feb 2010 for OPeNDAP Hyrax Back End Server (BES) by  doxygen 1.6.1