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