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