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 }