Main Page | Class Hierarchy | Data Structures | File List | Data Fields | Globals

ofc_sgml.cpp

Go to the documentation of this file.
00001 /*************************************************************************** 00002 ofx_sgml.cpp 00003 ------------------- 00004 copyright : (C) 2002 by Benoit Grégoire 00005 email : bock@step.polymtl.ca 00006 ***************************************************************************/ 00012 /*************************************************************************** 00013 * * 00014 * This program is free software; you can redistribute it and/or modify * 00015 * it under the terms of the GNU General Public License as published by * 00016 * the Free Software Foundation; either version 2 of the License, or * 00017 * (at your option) any later version. * 00018 * * 00019 ***************************************************************************/ 00020 00021 #ifdef HAVE_CONFIG_H 00022 #include <config.h> 00023 #endif 00024 00025 #include <iostream> 00026 #include <stdlib.h> 00027 #include <string> 00028 #include "ParserEventGeneratorKit.h" 00029 #include "libofx.h" 00030 #include "ofx_utilities.hh" 00031 #include "messages.hh" 00032 #include "ofx_containers.hh" 00033 #include "ofc_sgml.hh" 00034 00035 using namespace std; 00036 00037 00038 extern SGMLApplication::OpenEntityPtr entity_ptr; 00039 extern SGMLApplication::Position position; 00040 extern OfxMainContainer * MainContainer; 00041 00044 class OFCApplication : public SGMLApplication{ 00045 private: 00046 OfxGenericContainer *curr_container_element; 00047 OfxGenericContainer *tmp_container_element; 00048 bool is_data_element; 00049 string incoming_data; 00050 LibofxContext * libofx_context; 00051 public: 00052 OFCApplication (LibofxContext * p_libofx_context) 00053 { 00054 MainContainer=NULL; 00055 curr_container_element = NULL; 00056 is_data_element = false; 00057 libofx_context=p_libofx_context; 00058 } 00059 00064 void startElement (const StartElementEvent & event) 00065 { 00066 string identifier; 00067 CharStringtostring (event.gi, identifier); 00068 message_out(PARSER,"startElement event received from OpenSP for element " + identifier); 00069 00070 position = event.pos; 00071 00072 switch (event.contentType) 00073 { 00074 case StartElementEvent::empty: message_out(ERROR,"StartElementEvent::empty\n"); 00075 break; 00076 case StartElementEvent::cdata: message_out(ERROR,"StartElementEvent::cdata\n"); 00077 break; 00078 case StartElementEvent::rcdata: message_out(ERROR,"StartElementEvent::rcdata\n"); 00079 break; 00080 case StartElementEvent::mixed: message_out(PARSER,"StartElementEvent::mixed"); 00081 is_data_element = true; 00082 break; 00083 case StartElementEvent::element: message_out(PARSER,"StartElementEvent::element"); 00084 is_data_element = false; 00085 break; 00086 default: 00087 message_out(ERROR,"Unknow SGML content type?!?!?!? OpenSP interface changed?"); 00088 } 00089 00090 if (is_data_element == false) 00091 { 00092 /*------- The following are OFC entities ---------------*/ 00093 00094 if (identifier == "OFC") 00095 { 00096 message_out (PARSER, "Element " + identifier + " found"); 00097 MainContainer = new OfxMainContainer (libofx_context, curr_container_element, identifier); 00098 curr_container_element = MainContainer; 00099 } 00100 else if (identifier == "STATUS") 00101 { 00102 message_out (PARSER, "Element " + identifier + " found"); 00103 curr_container_element = new OfxStatusContainer (libofx_context, curr_container_element, identifier); 00104 } 00105 else if (identifier == "ACCTSTMT") 00106 { 00107 message_out (PARSER, "Element " + identifier + " found"); 00108 curr_container_element = new OfxStatementContainer (libofx_context, curr_container_element, identifier); 00109 } 00110 else if (identifier == "STMTRS") 00111 { 00112 message_out (PARSER, "Element " + identifier + " found"); 00113 //STMTRS ignored, we will process it's attributes directly inside the STATEMENT, 00114 if(curr_container_element->type!="STATEMENT") 00115 { 00116 message_out(ERROR,"Element " + identifier + " found while not inside a STATEMENT container"); 00117 } 00118 else 00119 { 00120 curr_container_element = new OfxPushUpContainer (libofx_context, curr_container_element, identifier); 00121 } 00122 } 00123 else if (identifier == "GENTRN" || 00124 identifier == "STMTTRN") 00125 { 00126 message_out (PARSER, "Element " + identifier + " found"); 00127 curr_container_element = new OfxBankTransactionContainer (libofx_context, curr_container_element, identifier); 00128 } 00129 else if(identifier == "BUYDEBT" || 00130 identifier == "BUYMF" || 00131 identifier == "BUYOPT" || 00132 identifier == "BUYOTHER" || 00133 identifier == "BUYSTOCK" || 00134 identifier == "CLOSUREOPT" || 00135 identifier == "INCOME" || 00136 identifier == "INVEXPENSE" || 00137 identifier == "JRNLFUND" || 00138 identifier == "JRNLSEC" || 00139 identifier == "MARGININTEREST" || 00140 identifier == "REINVEST" || 00141 identifier == "RETOFCAP" || 00142 identifier == "SELLDEBT" || 00143 identifier == "SELLMF" || 00144 identifier == "SELLOPT" || 00145 identifier == "SELLOTHER" || 00146 identifier == "SELLSTOCK" || 00147 identifier == "SPLIT" || 00148 identifier == "TRANSFER" ) 00149 { 00150 message_out (PARSER, "Element " + identifier + " found"); 00151 curr_container_element = new OfxInvestmentTransactionContainer (libofx_context, curr_container_element, identifier); 00152 } 00153 /*The following is a list of OFX elements whose attributes will be processed by the parent container*/ 00154 else if (identifier == "INVBUY" || 00155 identifier == "INVSELL" || 00156 identifier == "INVTRAN" || 00157 identifier == "SECID") 00158 { 00159 message_out (PARSER, "Element " + identifier + " found"); 00160 curr_container_element = new OfxPushUpContainer (libofx_context, curr_container_element, identifier); 00161 } 00162 00163 /* The different types of accounts */ 00164 else if (identifier == "ACCOUNT"|| 00165 identifier == "ACCTFROM" ) 00166 { 00167 message_out (PARSER, "Element " + identifier + " found"); 00168 curr_container_element = new OfxAccountContainer (libofx_context, curr_container_element, identifier); 00169 } 00170 else if (identifier == "SECINFO") 00171 { 00172 message_out (PARSER, "Element " + identifier + " found"); 00173 curr_container_element = new OfxSecurityContainer (libofx_context, curr_container_element, identifier); 00174 } 00175 /* The different types of balances */ 00176 else if (identifier == "LEDGERBAL" || identifier == "AVAILBAL") 00177 { 00178 message_out (PARSER, "Element " + identifier + " found"); 00179 curr_container_element = new OfxBalanceContainer (libofx_context, curr_container_element, identifier); 00180 } 00181 else 00182 { 00183 /* We dont know this OFX element, so we create a dummy container */ 00184 curr_container_element = new OfxDummyContainer(libofx_context, curr_container_element, identifier); 00185 } 00186 } 00187 else 00188 { 00189 /* The element was a data element. OpenSP will call one or several data() callback with the data */ 00190 message_out (PARSER, "Data element " + identifier + " found"); 00191 /* There is a bug in OpenSP 1.3.4, which won't send endElement Event for some elements, and will instead send an error like "document type does not allow element "MESSAGE" here". Incoming_data should be empty in such a case, but it will not be if the endElement event was skiped. So we empty it, so at least the last element has a chance of having valid data */ 00192 if (incoming_data != "") 00193 { 00194 message_out (ERROR, "startElement: incoming_data should be empty! You are probably using OpenSP <= 1.3.4. The folowing data was lost: " + incoming_data ); 00195 incoming_data.assign (""); 00196 } 00197 } 00198 } 00199 00204 void endElement (const EndElementEvent & event) 00205 { 00206 string identifier; 00207 bool end_element_for_data_element; 00208 00209 CharStringtostring (event.gi, identifier); 00210 end_element_for_data_element=is_data_element; 00211 message_out(PARSER,"endElement event received from OpenSP for element " + identifier); 00212 00213 position = event.pos; 00214 if (curr_container_element == NULL) 00215 { 00216 message_out (ERROR,"Tried to close a "+identifier+" without a open element (NULL pointer)"); 00217 incoming_data.assign (""); 00218 } 00219 else //curr_container_element != NULL 00220 { 00221 if (end_element_for_data_element == true) 00222 { 00223 incoming_data = strip_whitespace(incoming_data); 00224 00225 curr_container_element->add_attribute (identifier, incoming_data); 00226 message_out (PARSER,"endElement: Added data '" + incoming_data + "' from " + identifier + " to " + curr_container_element->type + " container_element"); 00227 incoming_data.assign (""); 00228 is_data_element=false; 00229 } 00230 else 00231 { 00232 if (identifier == curr_container_element->tag_identifier) 00233 { 00234 if(incoming_data!="") 00235 { 00236 message_out(ERROR,"End tag for non data element "+identifier+", incoming data should be empty but contains: "+incoming_data+" DATA HAS BEEN LOST SOMEWHERE!"); 00237 } 00238 00239 if(identifier == "OFX") 00240 { 00241 /* The main container is a special case */ 00242 tmp_container_element = curr_container_element; 00243 curr_container_element = curr_container_element->getparent (); 00244 MainContainer->gen_event(); 00245 delete MainContainer; 00246 MainContainer = NULL; 00247 message_out (DEBUG, "Element " + identifier + " closed, MainContainer destroyed"); 00248 } 00249 else 00250 { 00251 tmp_container_element = curr_container_element; 00252 curr_container_element = curr_container_element->getparent (); 00253 if(MainContainer != NULL) 00254 { 00255 tmp_container_element->add_to_main_tree(); 00256 message_out (PARSER, "Element " + identifier + " closed, object added to MainContainer"); 00257 } 00258 else 00259 { 00260 message_out (ERROR, "MainContainer is NULL trying to add element " + identifier); 00261 } 00262 } 00263 } 00264 else 00265 { 00266 message_out (ERROR, "Tried to close a "+identifier+" but a "+curr_container_element->type+" is currently open."); 00267 } 00268 } 00269 } 00270 } 00271 00276 void data (const DataEvent & event) 00277 { 00278 string tmp; 00279 position = event.pos; 00280 AppendCharStringtostring (event.data, incoming_data); 00281 message_out(PARSER, "data event received from OpenSP, incoming_data is now: " + incoming_data); 00282 } 00283 00288 void error (const ErrorEvent & event) 00289 { 00290 string message; 00291 string string_buf; 00292 OfxMsgType error_type = ERROR; 00293 00294 position = event.pos; 00295 message = message + "OpenSP parser: "; 00296 switch (event.type){ 00297 case SGMLApplication::ErrorEvent::quantity: 00298 message = message + "quantity (Exceeding a quantity limit):"; 00299 error_type = ERROR; 00300 break; 00301 case SGMLApplication::ErrorEvent::idref: 00302 message = message + "idref (An IDREF to a non-existent ID):"; 00303 error_type = ERROR; 00304 break; 00305 case SGMLApplication::ErrorEvent::capacity: 00306 message = message + "capacity (Exceeding a capacity limit):"; 00307 error_type = ERROR; 00308 break; 00309 case SGMLApplication::ErrorEvent::otherError: 00310 message = message + "otherError (misc parse error):"; 00311 error_type = ERROR; 00312 break; 00313 case SGMLApplication::ErrorEvent::warning: 00314 message = message + "warning (Not actually an error.):"; 00315 error_type = WARNING; 00316 break; 00317 case SGMLApplication::ErrorEvent::info: 00318 message = message + "info (An informationnal message. Not actually an error):"; 00319 error_type = INFO; 00320 break; 00321 default: 00322 message = message + "OpenSP sent an unknown error to LibOFX (You probably have a newer version of OpenSP):"; 00323 } 00324 message = message + "\n" + CharStringtostring (event.message, string_buf); 00325 message_out (error_type, message); 00326 } 00327 00332 void openEntityChange (const OpenEntityPtr & para_entity_ptr) 00333 { 00334 message_out(DEBUG,"openEntityChange()\n"); 00335 entity_ptr = para_entity_ptr; 00336 00337 }; 00338 00339 private: 00340 }; 00341 00345 int ofc_proc_sgml(LibofxContext * libofx_context, int argc, char *argv[]) 00346 { 00347 message_out(DEBUG,"Begin ofx_proc_sgml()"); 00348 message_out(DEBUG,argv[0]); 00349 message_out(DEBUG,argv[1]); 00350 message_out(DEBUG,argv[2]); 00351 00352 ParserEventGeneratorKit parserKit; 00353 parserKit.setOption (ParserEventGeneratorKit::showOpenEntities); 00354 EventGenerator *egp = parserKit.makeEventGenerator (argc, argv); 00355 egp->inhibitMessages (true); /* Error output is handled by libofx not OpenSP */ 00356 OFCApplication *app = new OFCApplication(libofx_context); 00357 unsigned nErrors = egp->run (*app); /* Begin parsing */ 00358 delete egp; 00359 return nErrors > 0; 00360 }

Generated on Fri Oct 8 20:34:47 2004 for LibOFX by doxygen 1.3.7