29 #include "ParserEventGeneratorKit.h" 
   38 extern SGMLApplication::OpenEntityPtr 
entity_ptr;
 
   39 extern SGMLApplication::Position 
position;
 
   40 static const std::string MESSAGE_NON_SGML_CHAR = 
"non SGML character";
 
   51   std::string incoming_data; 
 
   53   unsigned errorCountToIgnore = 0;
 
   60     curr_container_element = NULL;
 
   61     is_data_element = 
false;
 
   62     libofx_context = p_libofx_context;
 
   69   unsigned getErrorCountToIgnore()
 const { 
return errorCountToIgnore; }
 
   78     message_out(
PARSER, 
"startElement event received from OpenSP for element " + identifier);
 
   82     switch (event.contentType)
 
   84     case StartElementEvent::empty:
 
   87     case StartElementEvent::cdata:
 
   90     case StartElementEvent::rcdata:
 
   93     case StartElementEvent::mixed:
 
   95       is_data_element = 
true;
 
   97     case StartElementEvent::element:
 
   99       is_data_element = 
false;
 
  102       message_out(
ERROR, 
"Unknown SGML content type?!?!?!? OpenSP interface changed?");
 
  105     if (is_data_element == 
false)
 
  109       if (identifier == 
"OFX")
 
  112         MainContainer = 
new OfxMainContainer (libofx_context, curr_container_element, identifier);
 
  113         curr_container_element = MainContainer;
 
  115       else if (identifier == 
"STATUS")
 
  118         curr_container_element = 
new OfxStatusContainer (libofx_context, curr_container_element, identifier);
 
  120       else if (identifier == 
"STMTRS" ||
 
  121                identifier == 
"CCSTMTRS" ||
 
  122                identifier == 
"INVSTMTRS")
 
  125         curr_container_element = 
new OfxStatementContainer (libofx_context, curr_container_element, identifier);
 
  127       else if (identifier == 
"BANKTRANLIST" || identifier == 
"INVTRANLIST")
 
  131         if (curr_container_element && curr_container_element->
type != 
"STATEMENT")
 
  133           message_out(
ERROR, 
"Element " + identifier + 
" found while not inside a STATEMENT container");
 
  137           curr_container_element = 
new OfxPushUpContainer (libofx_context, curr_container_element, identifier);
 
  140       else if (identifier == 
"STMTTRN")
 
  143         if (curr_container_element && curr_container_element->
type == 
"INVESTMENT")
 
  146           curr_container_element = 
new OfxPushUpContainer (libofx_context, curr_container_element, identifier);
 
  153       else if (identifier == 
"BUYDEBT" ||
 
  154                identifier == 
"BUYMF" ||
 
  155                identifier == 
"BUYOPT" ||
 
  156                identifier == 
"BUYOTHER" ||
 
  157                identifier == 
"BUYSTOCK" ||
 
  158                identifier == 
"CLOSUREOPT" ||
 
  159                identifier == 
"INCOME" ||
 
  160                identifier == 
"INVEXPENSE" ||
 
  161                identifier == 
"JRNLFUND" ||
 
  162                identifier == 
"JRNLSEC" ||
 
  163                identifier == 
"MARGININTEREST" ||
 
  164                identifier == 
"REINVEST" ||
 
  165                identifier == 
"RETOFCAP" ||
 
  166                identifier == 
"SELLDEBT" ||
 
  167                identifier == 
"SELLMF" ||
 
  168                identifier == 
"SELLOPT" ||
 
  169                identifier == 
"SELLOTHER" ||
 
  170                identifier == 
"SELLSTOCK" ||
 
  171                identifier == 
"SPLIT" ||
 
  172                identifier == 
"TRANSFER" ||
 
  173                identifier == 
"INVBANKTRAN" )
 
  179       else if (identifier == 
"INVBUY" ||
 
  180                identifier == 
"INVSELL" ||
 
  181                identifier == 
"INVTRAN" ||
 
  182                identifier == 
"SECINFO" ||
 
  183                identifier == 
"SECID" ||
 
  184                identifier == 
"CURRENCY" ||
 
  185                identifier == 
"ORIGCURRENCY")
 
  188         curr_container_element = 
new OfxPushUpContainer (libofx_context, curr_container_element, identifier);
 
  192       else if (identifier == 
"BANKACCTINFO" || identifier == 
"CCACCTINFO" || identifier == 
"INVACCTINFO")
 
  195         curr_container_element = 
new OfxPushUpContainer (libofx_context, curr_container_element, identifier);
 
  199       else if (identifier == 
"BANKACCTFROM" || identifier == 
"CCACCTFROM" || identifier == 
"INVACCTFROM")
 
  203         if (curr_container_element && 
 
  204             (  curr_container_element->
type == 
"STATEMENT" 
  208           curr_container_element = 
new OfxAccountContainer (libofx_context, curr_container_element, identifier);
 
  211           curr_container_element = 
new OfxDummyContainer (libofx_context, curr_container_element, identifier);
 
  213       else if (identifier == 
"STOCKINFO" || identifier == 
"OPTINFO" ||
 
  214                identifier == 
"DEBTINFO" || identifier == 
"MFINFO" || identifier == 
"OTHERINFO")
 
  217         curr_container_element = 
new OfxSecurityContainer (libofx_context, curr_container_element, identifier);
 
  220       else if (identifier == 
"LEDGERBAL" ||
 
  221                identifier == 
"AVAILBAL" ||
 
  222                identifier == 
"INVBAL")
 
  225         curr_container_element = 
new OfxBalanceContainer (libofx_context, curr_container_element, identifier);
 
  227       else if (identifier == 
"INVPOS")
 
  230         curr_container_element = 
new OfxPositionContainer (libofx_context, curr_container_element, identifier);
 
  235         curr_container_element = 
new OfxDummyContainer(libofx_context, curr_container_element, identifier);
 
  242       if (identifier == 
"INV401K")
 
  246         curr_container_element = 
new OfxInv401kContainer (libofx_context, curr_container_element, identifier);
 
  248       if (identifier == 
"INV401KBAL")
 
  251         curr_container_element = 
new OfxBalanceContainer (libofx_context, curr_container_element, identifier);
 
  258         if (incoming_data != 
"")
 
  260           message_out (
ERROR, 
"startElement: incoming_data should be empty! You are probably using OpenSP <= 1.3.4.  The following data was lost: " + incoming_data );
 
  261           incoming_data.assign (
"");
 
  274     bool end_element_for_data_element = is_data_element;
 
  275     message_out(
PARSER, 
"endElement event received from OpenSP for element " + identifier);
 
  278     if (curr_container_element == NULL)
 
  280       message_out (
ERROR, 
"Tried to close a " + identifier + 
" without a open element (NULL pointer)");
 
  281       incoming_data.assign (
"");
 
  285       if (end_element_for_data_element == 
true)
 
  289         curr_container_element->
add_attribute (identifier, incoming_data);
 
  290         message_out (
PARSER, 
"endElement: Added data '" + incoming_data + 
"' from " + identifier + 
" to " + curr_container_element->
type + 
" container_element");
 
  291         incoming_data.assign (
"");
 
  292         is_data_element = 
false;
 
  298           if (incoming_data != 
"")
 
  300             message_out(
ERROR, 
"End tag for non data element " + identifier + 
", incoming data should be empty but contains: " + incoming_data + 
" DATA HAS BEEN LOST SOMEWHERE!");
 
  303           if (identifier == 
"OFX")
 
  306             tmp_container_element = curr_container_element;
 
  307             curr_container_element = curr_container_element->
getparent ();
 
  308             if (curr_container_element == NULL)
 
  311               curr_container_element = tmp_container_element;
 
  313             if (MainContainer != NULL)
 
  316               delete MainContainer;
 
  317               MainContainer = NULL;
 
  318               curr_container_element = NULL;
 
  319               message_out (
DEBUG, 
"Element " + identifier + 
" closed, MainContainer destroyed");
 
  323               message_out (
DEBUG, 
"Element " + identifier + 
" closed, but there was no MainContainer to destroy (probably a malformed file)!");
 
  328             tmp_container_element = curr_container_element;
 
  329             curr_container_element = curr_container_element->
getparent ();
 
  330             if (MainContainer != NULL)
 
  335               if (identifier == 
"CURRENCY" || identifier == 
"ORIGCURRENCY")
 
  337                 tmp_container_element->
add_attribute (identifier, incoming_data);
 
  338                 message_out (
DEBUG, 
"Element " + identifier + 
" closed, container " + tmp_container_element->
type + 
" updated");
 
  343                 message_out (
PARSER, 
"Element " + identifier + 
" closed, object added to MainContainer");
 
  348               message_out (
ERROR, 
"MainContainer is NULL trying to add element " + identifier);
 
  354           message_out (
ERROR, 
"Tried to close a " + identifier + 
" but a " + curr_container_element->
type + 
" is currently open.");
 
  364   void data (
const DataEvent & event)
 
  369     message_out(
PARSER, 
"data event received from OpenSP, incoming_data is now: " + incoming_data);
 
  376   void error (
const ErrorEvent & event)
 
  383     message = message + 
"OpenSP parser: ";
 
  386     case SGMLApplication::ErrorEvent::quantity:
 
  387       message = message + 
"quantity (Exceeding a quantity limit):";
 
  390     case SGMLApplication::ErrorEvent::idref:
 
  391       message = message + 
"idref (An IDREF to a non-existent ID):";
 
  394     case SGMLApplication::ErrorEvent::capacity:
 
  395       message = message + 
"capacity (Exceeding a capacity limit):";
 
  398     case SGMLApplication::ErrorEvent::otherError:
 
  403       if (eventMessage.find(MESSAGE_NON_SGML_CHAR) != std::string::npos) {
 
  404         ++errorCountToIgnore;
 
  405         message = message + 
"ignored character error:";
 
  408         message = message + 
"otherError (misc parse error):";
 
  412     case SGMLApplication::ErrorEvent::warning:
 
  413       message = message + 
"warning (Not actually an error.):";
 
  416     case SGMLApplication::ErrorEvent::info:
 
  417       message =  message + 
"info (An informationnal message.  Not actually an error):";
 
  421       message = message + 
"OpenSP sent an unknown error to LibOFX (You probably have a newer version of OpenSP):";
 
  423     message =   message + 
"\n" + eventMessage;
 
  452   ParserEventGeneratorKit parserKit;
 
  453   parserKit.setOption (ParserEventGeneratorKit::showOpenEntities);
 
  454   EventGenerator *egp = parserKit.makeEventGenerator (argc, argv);
 
  455   egp->inhibitMessages (
true);  
 
  457   unsigned originalErrorCount = egp->run (app); 
 
  458   unsigned nErrors = originalErrorCount - app.getErrorCountToIgnore();