00001
00002
00003
00004
00005
00006
00012
00013
00014
00015
00016
00017
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 "ofx_sgml.hh"
00034
00035 using namespace std;
00036
00037 OfxMainContainer * MainContainer = NULL;
00038 extern SGMLApplication::OpenEntityPtr entity_ptr;
00039 extern SGMLApplication::Position position;
00040
00041
00044 class OFXApplication : public SGMLApplication
00045 {
00046 private:
00047 OfxGenericContainer *curr_container_element;
00048 OfxGenericContainer *tmp_container_element;
00049 bool is_data_element;
00050 string incoming_data;
00051 LibofxContext * libofx_context;
00052
00053 public:
00054
00055 OFXApplication (LibofxContext * p_libofx_context)
00056 {
00057 MainContainer=NULL;
00058 curr_container_element = NULL;
00059 is_data_element = false;
00060 libofx_context=p_libofx_context;
00061 }
00062 ~OFXApplication()
00063 {
00064 message_out(DEBUG,"Entering the OFXApplication's destructor");
00065 }
00066
00071 void startElement (const StartElementEvent & event)
00072 {
00073 string identifier;
00074 CharStringtostring (event.gi, identifier);
00075 message_out(PARSER,"startElement event received from OpenSP for element " + identifier);
00076
00077 position = event.pos;
00078
00079 switch (event.contentType)
00080 {
00081 case StartElementEvent::empty: message_out(ERROR,"StartElementEvent::empty\n");
00082 break;
00083 case StartElementEvent::cdata: message_out(ERROR,"StartElementEvent::cdata\n");
00084 break;
00085 case StartElementEvent::rcdata: message_out(ERROR,"StartElementEvent::rcdata\n");
00086 break;
00087 case StartElementEvent::mixed: message_out(PARSER,"StartElementEvent::mixed");
00088 is_data_element = true;
00089 break;
00090 case StartElementEvent::element: message_out(PARSER,"StartElementEvent::element");
00091 is_data_element = false;
00092 break;
00093 default:
00094 message_out(ERROR,"Unknow SGML content type?!?!?!? OpenSP interface changed?");
00095 }
00096
00097 if (is_data_element == false)
00098 {
00099
00100
00101 if (identifier == "OFX")
00102 {
00103 message_out (PARSER, "Element " + identifier + " found");
00104 MainContainer = new OfxMainContainer (libofx_context, curr_container_element, identifier);
00105 curr_container_element = MainContainer;
00106 }
00107 else if (identifier == "STATUS")
00108 {
00109 message_out (PARSER, "Element " + identifier + " found");
00110 curr_container_element = new OfxStatusContainer (libofx_context, curr_container_element, identifier);
00111 }
00112 else if (identifier == "STMTRS" ||
00113 identifier == "CCSTMTRS" ||
00114 identifier == "INVSTMTRS")
00115 {
00116 message_out (PARSER, "Element " + identifier + " found");
00117 curr_container_element = new OfxStatementContainer (libofx_context, curr_container_element, identifier);
00118 }
00119 else if (identifier == "BANKTRANLIST")
00120 {
00121 message_out (PARSER, "Element " + identifier + " found");
00122
00123 if(curr_container_element->type!="STATEMENT")
00124 {
00125 message_out(ERROR,"Element " + identifier + " found while not inside a STATEMENT container");
00126 }
00127 else
00128 {
00129 curr_container_element = new OfxPushUpContainer (libofx_context, curr_container_element, identifier);
00130 }
00131 }
00132 else if (identifier == "STMTTRN")
00133 {
00134 message_out (PARSER, "Element " + identifier + " found");
00135 curr_container_element = new OfxBankTransactionContainer (libofx_context, curr_container_element, identifier);
00136 }
00137 else if(identifier == "BUYDEBT" ||
00138 identifier == "BUYMF" ||
00139 identifier == "BUYOPT" ||
00140 identifier == "BUYOTHER" ||
00141 identifier == "BUYSTOCK" ||
00142 identifier == "CLOSUREOPT" ||
00143 identifier == "INCOME" ||
00144 identifier == "INVEXPENSE" ||
00145 identifier == "JRNLFUND" ||
00146 identifier == "JRNLSEC" ||
00147 identifier == "MARGININTEREST" ||
00148 identifier == "REINVEST" ||
00149 identifier == "RETOFCAP" ||
00150 identifier == "SELLDEBT" ||
00151 identifier == "SELLMF" ||
00152 identifier == "SELLOPT" ||
00153 identifier == "SELLOTHER" ||
00154 identifier == "SELLSTOCK" ||
00155 identifier == "SPLIT" ||
00156 identifier == "TRANSFER" )
00157 {
00158 message_out (PARSER, "Element " + identifier + " found");
00159 curr_container_element = new OfxInvestmentTransactionContainer (libofx_context, curr_container_element, identifier);
00160 }
00161
00162 else if (identifier == "INVBUY" ||
00163 identifier == "INVSELL" ||
00164 identifier == "INVTRAN" ||
00165 identifier == "SECID")
00166 {
00167 message_out (PARSER, "Element " + identifier + " found");
00168 curr_container_element = new OfxPushUpContainer (libofx_context, curr_container_element, identifier);
00169 }
00170
00171
00172 else if (identifier == "BANKACCTFROM" || identifier == "CCACCTFROM" || identifier == "INVACCTFROM")
00173 {
00174 message_out (PARSER, "Element " + identifier + " found");
00175 curr_container_element = new OfxAccountContainer (libofx_context, curr_container_element, identifier);
00176 }
00177 else if (identifier == "SECINFO")
00178 {
00179 message_out (PARSER, "Element " + identifier + " found");
00180 curr_container_element = new OfxSecurityContainer (libofx_context, curr_container_element, identifier);
00181 }
00182
00183 else if (identifier == "LEDGERBAL" || identifier == "AVAILBAL")
00184 {
00185 message_out (PARSER, "Element " + identifier + " found");
00186 curr_container_element = new OfxBalanceContainer (libofx_context, curr_container_element, identifier);
00187 }
00188 else
00189 {
00190
00191 curr_container_element = new OfxDummyContainer(libofx_context, curr_container_element, identifier);
00192 }
00193 }
00194 else
00195 {
00196
00197 message_out (PARSER, "Data element " + identifier + " found");
00198
00199 if (incoming_data != "")
00200 {
00201 message_out (ERROR, "startElement: incoming_data should be empty! You are probably using OpenSP <= 1.3.4. The folowing data was lost: " + incoming_data );
00202 incoming_data.assign ("");
00203 }
00204 }
00205 }
00206
00211 void endElement (const EndElementEvent & event)
00212 {
00213 string identifier;
00214 bool end_element_for_data_element;
00215
00216 CharStringtostring (event.gi, identifier);
00217 end_element_for_data_element=is_data_element;
00218 message_out(PARSER,"endElement event received from OpenSP for element " + identifier);
00219
00220 position = event.pos;
00221 if (curr_container_element == NULL)
00222 {
00223 message_out (ERROR,"Tried to close a "+identifier+" without a open element (NULL pointer)");
00224 incoming_data.assign ("");
00225 }
00226 else
00227 {
00228 if (end_element_for_data_element == true)
00229 {
00230 incoming_data = strip_whitespace(incoming_data);
00231
00232 curr_container_element->add_attribute (identifier, incoming_data);
00233 message_out (PARSER,"endElement: Added data '" + incoming_data + "' from " + identifier + " to " + curr_container_element->type + " container_element");
00234 incoming_data.assign ("");
00235 is_data_element=false;
00236 }
00237 else
00238 {
00239 if (identifier == curr_container_element->tag_identifier)
00240 {
00241 if(incoming_data!="")
00242 {
00243 message_out(ERROR,"End tag for non data element "+identifier+", incoming data should be empty but contains: "+incoming_data+" DATA HAS BEEN LOST SOMEWHERE!");
00244 }
00245
00246 if(identifier == "OFX")
00247 {
00248
00249 tmp_container_element = curr_container_element;
00250 curr_container_element = curr_container_element->getparent ();
00251 MainContainer->gen_event();
00252 delete MainContainer;
00253 MainContainer = NULL;
00254 message_out (DEBUG, "Element " + identifier + " closed, MainContainer destroyed");
00255 }
00256 else
00257 {
00258 tmp_container_element = curr_container_element;
00259 curr_container_element = curr_container_element->getparent ();
00260 if(MainContainer != NULL)
00261 {
00262 tmp_container_element->add_to_main_tree();
00263 message_out (PARSER, "Element " + identifier + " closed, object added to MainContainer");
00264 }
00265 else
00266 {
00267 message_out (ERROR, "MainContainer is NULL trying to add element " + identifier);
00268 }
00269 }
00270 }
00271 else
00272 {
00273 message_out (ERROR, "Tried to close a "+identifier+" but a "+curr_container_element->type+" is currently open.");
00274 }
00275 }
00276 }
00277 }
00278
00283 void data (const DataEvent & event)
00284 {
00285 string tmp;
00286 position = event.pos;
00287 AppendCharStringtostring (event.data, incoming_data);
00288 message_out(PARSER, "data event received from OpenSP, incoming_data is now: " + incoming_data);
00289 }
00290
00295 void error (const ErrorEvent & event)
00296 {
00297 string message;
00298 string string_buf;
00299 OfxMsgType error_type = ERROR;
00300
00301 position = event.pos;
00302 message = message + "OpenSP parser: ";
00303 switch (event.type){
00304 case SGMLApplication::ErrorEvent::quantity:
00305 message = message + "quantity (Exceeding a quantity limit):";
00306 error_type = ERROR;
00307 break;
00308 case SGMLApplication::ErrorEvent::idref:
00309 message = message + "idref (An IDREF to a non-existent ID):";
00310 error_type = ERROR;
00311 break;
00312 case SGMLApplication::ErrorEvent::capacity:
00313 message = message + "capacity (Exceeding a capacity limit):";
00314 error_type = ERROR;
00315 break;
00316 case SGMLApplication::ErrorEvent::otherError:
00317 message = message + "otherError (misc parse error):";
00318 error_type = ERROR;
00319 break;
00320 case SGMLApplication::ErrorEvent::warning:
00321 message = message + "warning (Not actually an error.):";
00322 error_type = WARNING;
00323 break;
00324 case SGMLApplication::ErrorEvent::info:
00325 message = message + "info (An informationnal message. Not actually an error):";
00326 error_type = INFO;
00327 break;
00328 default:
00329 message = message + "OpenSP sent an unknown error to LibOFX (You probably have a newer version of OpenSP):";
00330 }
00331 message = message + "\n" + CharStringtostring (event.message, string_buf);
00332 message_out (error_type, message);
00333 }
00334
00339 void openEntityChange (const OpenEntityPtr & para_entity_ptr)
00340 {
00341 message_out(DEBUG,"openEntityChange()\n");
00342 entity_ptr = para_entity_ptr;
00343
00344 };
00345
00346 private:
00347 };
00348
00352 int ofx_proc_sgml(LibofxContext * libofx_context, int argc, char *argv[])
00353 {
00354 message_out(DEBUG,"Begin ofx_proc_sgml()");
00355 message_out(DEBUG,argv[0]);
00356 message_out(DEBUG,argv[1]);
00357 message_out(DEBUG,argv[2]);
00358
00359 ParserEventGeneratorKit parserKit;
00360 parserKit.setOption (ParserEventGeneratorKit::showOpenEntities);
00361 EventGenerator *egp = parserKit.makeEventGenerator (argc, argv);
00362 egp->inhibitMessages (true);
00363 OFXApplication *app = new OFXApplication(libofx_context);
00364 unsigned nErrors = egp->run (*app);
00365 delete egp;
00366 return nErrors > 0;
00367 }