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