DataDictionary.cpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (c) 2001-2014
00003 **
00004 ** This file is part of the QuickFIX FIX Engine
00005 **
00006 ** This file may be distributed under the terms of the quickfixengine.org
00007 ** license as defined by quickfixengine.org and appearing in the file
00008 ** LICENSE included in the packaging of this file.
00009 **
00010 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00011 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00012 **
00013 ** See http://www.quickfixengine.org/LICENSE for licensing information.
00014 **
00015 ** Contact ask@quickfixengine.org if any conditions of this licensing are
00016 ** not clear to you.
00017 **
00018 ****************************************************************************/
00019 
00020 #ifdef _MSC_VER
00021 #include "stdafx.h"
00022 #else
00023 #include "config.h"
00024 #endif
00025 
00026 #include "DataDictionary.h"
00027 #include "Message.h"
00028 #include <fstream>
00029 #include <memory>
00030 
00031 #ifdef HAVE_LIBXML
00032 #include "LIBXML_DOMDocument.h"
00033 #elif _MSC_VER
00034 #include "MSXML_DOMDocument.h"
00035 #else
00036 #include "LIBXML_DOMDocument.h"
00037 #endif
00038 
00039 #ifdef _MSC_VER
00040 #define RESET_AUTO_PTR(OLD, NEW) OLD = NEW;
00041 #else
00042 #define RESET_AUTO_PTR(OLD, NEW) OLD.reset( NEW.release() );
00043 #endif
00044 
00045 namespace FIX
00046 {
00047 DataDictionary::DataDictionary()
00048 : m_hasVersion( false ), m_checkFieldsOutOfOrder( true ),
00049   m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true )
00050 {}
00051 
00052 DataDictionary::DataDictionary( std::istream& stream )
00053 throw( ConfigError )
00054 : m_hasVersion( false ), m_checkFieldsOutOfOrder( true ),
00055   m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true )
00056 {
00057   readFromStream( stream );
00058 }
00059 
00060 DataDictionary::DataDictionary( const std::string& url )
00061 throw( ConfigError )
00062 : m_hasVersion( false ), m_checkFieldsOutOfOrder( true ),
00063   m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true ),
00064   m_orderedFieldsArray(0)
00065 {
00066   readFromURL( url );
00067 }
00068 
00069 DataDictionary::DataDictionary( const DataDictionary& copy )
00070 {
00071   *this = copy;
00072 }
00073 
00074 DataDictionary::~DataDictionary()
00075 {
00076   FieldToGroup::iterator i;
00077   for ( i = m_groups.begin(); i != m_groups.end(); ++i )
00078   {
00079     const FieldPresenceMap& presenceMap = i->second;
00080 
00081     FieldPresenceMap::const_iterator iter = presenceMap.begin();
00082     for ( ; iter != presenceMap.end(); ++iter )
00083       delete iter->second.second;
00084 }
00085 }
00086 
00087 DataDictionary& DataDictionary::operator=( const DataDictionary& rhs )
00088 {
00089   m_hasVersion = rhs.m_hasVersion;
00090   m_checkFieldsOutOfOrder = rhs.m_checkFieldsOutOfOrder;
00091   m_checkFieldsHaveValues = rhs.m_checkFieldsHaveValues;
00092   m_checkUserDefinedFields = rhs.m_checkUserDefinedFields;
00093   m_beginString = rhs.m_beginString;
00094   m_messageFields = rhs.m_messageFields;
00095   m_requiredFields = rhs.m_requiredFields;
00096   m_messages = rhs.m_messages;
00097   m_fields = rhs.m_fields;
00098   m_orderedFields = rhs.m_orderedFields;
00099   m_orderedFieldsArray = rhs.m_orderedFieldsArray;
00100   m_headerFields = rhs.m_headerFields;
00101   m_trailerFields = rhs.m_trailerFields;
00102   m_fieldTypes = rhs.m_fieldTypes;
00103   m_fieldValues = rhs.m_fieldValues;
00104   m_fieldNames = rhs.m_fieldNames;
00105   m_names = rhs.m_names;
00106   m_valueNames = rhs.m_valueNames;
00107   m_dataFields = rhs.m_dataFields;
00108 
00109   FieldToGroup::const_iterator i = rhs.m_groups.begin();
00110   for ( ; i != rhs.m_groups.end(); ++i )
00111   {
00112     const FieldPresenceMap& presenceMap = i->second;
00113 
00114     FieldPresenceMap::const_iterator iter = presenceMap.begin();
00115     for ( ; iter != presenceMap.end(); ++iter )
00116     {
00117       addGroup( iter->first, i->first, iter->second.first, *iter->second.second );
00118   }
00119   }
00120   return *this;
00121 }
00122 
00123 void DataDictionary::validate( const Message& message,
00124                                const DataDictionary* const pSessionDD,
00125                                const DataDictionary* const pAppDD )
00126 throw( FIX::Exception )
00127 {  
00128   const Header& header = message.getHeader();
00129   const BeginString& beginString = FIELD_GET_REF( header, BeginString );
00130   const MsgType& msgType = FIELD_GET_REF( header, MsgType );
00131   if ( pSessionDD != 0 && pSessionDD->m_hasVersion )
00132   {
00133     if( pSessionDD->getVersion() != beginString )
00134     {
00135       throw UnsupportedVersion();
00136     }
00137   }
00138 
00139   int field = 0;
00140   if( (pSessionDD !=0 && pSessionDD->m_checkFieldsOutOfOrder) || 
00141       (pAppDD != 0 && pAppDD->m_checkFieldsOutOfOrder) )
00142   {
00143     if ( !message.hasValidStructure(field) )
00144       throw TagOutOfOrder(field);
00145   }
00146 
00147   if ( pAppDD != 0 && pAppDD->m_hasVersion )
00148   {
00149     pAppDD->checkMsgType( msgType );
00150     pAppDD->checkHasRequired( message.getHeader(), message, message.getTrailer(), msgType );
00151   }
00152 
00153   if( pSessionDD != 0 )
00154   {
00155     pSessionDD->iterate( message.getHeader(), msgType );
00156     pSessionDD->iterate( message.getTrailer(), msgType );
00157   }
00158 
00159   if( pAppDD != 0 )
00160   {
00161     pAppDD->iterate( message, msgType );
00162   }
00163 }
00164 
00165 void DataDictionary::iterate( const FieldMap& map, const MsgType& msgType ) const
00166 {
00167   int lastField = 0;
00168 
00169   FieldMap::iterator i;
00170   for ( i = map.begin(); i != map.end(); ++i )
00171   {
00172     const FieldBase& field = i->second;
00173     if( i != map.begin() && (field.getField() == lastField) )
00174       throw RepeatedTag( lastField );
00175     checkHasValue( field );
00176 
00177     if ( m_hasVersion )
00178     {
00179       checkValidFormat( field );
00180       checkValue( field );
00181     }
00182 
00183     if ( m_beginString.getValue().length() && shouldCheckTag(field) )
00184     {
00185       checkValidTagNumber( field );
00186       if ( !Message::isHeaderField( field, this )
00187            && !Message::isTrailerField( field, this ) )
00188       {
00189         checkIsInMessage( field, msgType );
00190         checkGroupCount( field, map, msgType );
00191       }
00192     }
00193     lastField = field.getField();
00194   }
00195 }
00196 
00197 void DataDictionary::readFromURL( const std::string& url )
00198 throw( ConfigError )
00199 {
00200 #ifdef HAVE_LIBXML
00201   DOMDocumentPtr pDoc = DOMDocumentPtr(new LIBXML_DOMDocument());
00202 #elif _MSC_VER
00203   DOMDocumentPtr pDoc = DOMDocumentPtr(new MSXML_DOMDocument());
00204 #else
00205   DOMDocumentPtr pDoc = DOMDocumentPtr(new LIBXML_DOMDocument());
00206 #endif
00207 
00208   if(!pDoc->load(url))
00209     throw ConfigError(url + ": Could not parse data dictionary file");
00210 
00211   try
00212   {
00213     readFromDocument( pDoc );
00214   }
00215   catch( ConfigError& e )
00216   {
00217     throw ConfigError( url + ": " + e.what() );
00218   }
00219 }
00220 
00221 void DataDictionary::readFromStream( std::istream& stream )
00222 throw( ConfigError )
00223 {
00224 #ifdef HAVE_LIBXML
00225   DOMDocumentPtr pDoc = DOMDocumentPtr(new LIBXML_DOMDocument());
00226 #elif _MSC_VER
00227   DOMDocumentPtr pDoc = DOMDocumentPtr(new MSXML_DOMDocument());
00228 #else
00229   DOMDocumentPtr pDoc = DOMDocumentPtr(new LIBXML_DOMDocument());
00230 #endif
00231 
00232   if(!pDoc->load(stream))
00233     throw ConfigError("Could not parse data dictionary stream");
00234 
00235   readFromDocument( pDoc );
00236 }
00237 
00238 void DataDictionary::readFromDocument( DOMDocumentPtr pDoc )
00239 throw( ConfigError )
00240 {
00241   // VERSION
00242   DOMNodePtr pFixNode = pDoc->getNode("/fix");
00243   if(!pFixNode.get())
00244     throw ConfigError("Could not parse data dictionary file"
00245                       ", or no <fix> node found at root");
00246   DOMAttributesPtr attrs = pFixNode->getAttributes();
00247   std::string type = "FIX";
00248   if(attrs->get("type", type))
00249   {
00250     if(type != "FIX" && type != "FIXT")
00251       throw ConfigError("type attribute must be FIX or FIXT");
00252   }
00253   std::string major;
00254   if(!attrs->get("major", major))
00255     throw ConfigError("major attribute not found on <fix>");
00256   std::string minor;
00257   if(!attrs->get("minor", minor))
00258     throw ConfigError("minor attribute not found on <fix>");
00259   setVersion(type + "." + major + "." + minor);
00260 
00261   // FIELDS
00262   DOMNodePtr pFieldsNode = pDoc->getNode("/fix/fields");
00263   if(!pFieldsNode.get())
00264     throw ConfigError("<fields> section not found in data dictionary");
00265 
00266   DOMNodePtr pFieldNode = pFieldsNode->getFirstChildNode();
00267   if(!pFieldNode.get()) throw ConfigError("No fields defined");
00268 
00269   while(pFieldNode.get())
00270   {
00271     if(pFieldNode->getName() == "field")
00272     {
00273       DOMAttributesPtr attrs = pFieldNode->getAttributes();
00274       std::string name;
00275       if(!attrs->get("name", name))
00276         throw ConfigError("<field> does not have a name attribute");
00277       std::string number;
00278       if(!attrs->get("number", number))
00279         throw ConfigError("<field> " + name + " does not have a number attribute");
00280       int num = atol(number.c_str());
00281       std::string type;
00282       if(!attrs->get("type", type))
00283         throw ConfigError("<field> " + name + " does not have a type attribute");
00284       addField(num);
00285       addFieldType(num, XMLTypeToType(type));
00286       addFieldName(num, name);
00287 
00288       DOMNodePtr pFieldValueNode = pFieldNode->getFirstChildNode();
00289       while(pFieldValueNode.get())
00290       {
00291         if(pFieldValueNode->getName() == "value")
00292         {
00293           DOMAttributesPtr attrs = pFieldValueNode->getAttributes();
00294           std::string enumeration;
00295           if(!attrs->get("enum", enumeration))
00296             throw ConfigError("<value> does not have enum attribute in field " + name);
00297           addFieldValue(num, enumeration);
00298           std::string description;
00299           if(attrs->get("description", description))
00300             addValueName(num, enumeration, description);
00301         }
00302         RESET_AUTO_PTR(pFieldValueNode, pFieldValueNode->getNextSiblingNode());
00303       }
00304     }
00305     RESET_AUTO_PTR(pFieldNode, pFieldNode->getNextSiblingNode());
00306   }
00307 
00308   // HEADER
00309   if( type == "FIXT" || (type == "FIX" && major < "5") )
00310   {
00311     DOMNodePtr pHeaderNode = pDoc->getNode("/fix/header");
00312     if(!pHeaderNode.get())
00313       throw ConfigError("<header> section not found in data dictionary");
00314 
00315     DOMNodePtr pHeaderFieldNode = pHeaderNode->getFirstChildNode();
00316     if(!pHeaderFieldNode.get()) throw ConfigError("No header fields defined");
00317 
00318     while(pHeaderFieldNode.get())
00319     {
00320       if(pHeaderFieldNode->getName() == "field" || pHeaderFieldNode->getName() == "group" )
00321       {
00322         DOMAttributesPtr attrs = pHeaderFieldNode->getAttributes();
00323         std::string name;
00324         if(!attrs->get("name", name))
00325           throw ConfigError("<field> does not have a name attribute");
00326         std::string required = "false";
00327         attrs->get("required", required);
00328         addHeaderField(lookupXMLFieldNumber(pDoc.get(), name), required == "true");
00329       }
00330       if(pHeaderFieldNode->getName() == "group")
00331       {
00332         DOMAttributesPtr attrs = pHeaderFieldNode->getAttributes();
00333         std::string required;
00334         attrs->get("required", required);
00335         bool isRequired = (required == "Y" || required == "y");
00336         addXMLGroup(pDoc.get(), pHeaderFieldNode.get(), "_header_", *this, isRequired);
00337       }
00338 
00339       RESET_AUTO_PTR(pHeaderFieldNode, pHeaderFieldNode->getNextSiblingNode());
00340     }
00341   }
00342 
00343   // TRAILER
00344     if( type == "FIXT" || (type == "FIX" && major < "5") )
00345     {
00346     DOMNodePtr pTrailerNode = pDoc->getNode("/fix/trailer");
00347     if(!pTrailerNode.get())
00348       throw ConfigError("<trailer> section not found in data dictionary");
00349 
00350     DOMNodePtr pTrailerFieldNode = pTrailerNode->getFirstChildNode();
00351     if(!pTrailerFieldNode.get()) throw ConfigError("No trailer fields defined");
00352 
00353     while(pTrailerFieldNode.get())
00354     {
00355       if(pTrailerFieldNode->getName() == "field" || pTrailerFieldNode->getName() == "group" )
00356       {
00357         DOMAttributesPtr attrs = pTrailerFieldNode->getAttributes();
00358         std::string name;
00359         if(!attrs->get("name", name))
00360           throw ConfigError("<field> does not have a name attribute");
00361         std::string required = "false";
00362         attrs->get("required", required);
00363         addTrailerField(lookupXMLFieldNumber(pDoc.get(), name), required == "true");
00364       }
00365       if(pTrailerFieldNode->getName() == "group")
00366       {
00367         DOMAttributesPtr attrs = pTrailerFieldNode->getAttributes();
00368         std::string required;
00369         attrs->get("required", required);
00370         bool isRequired = (required == "Y" || required == "y");
00371         addXMLGroup(pDoc.get(), pTrailerFieldNode.get(), "_trailer_", *this, isRequired);
00372       }
00373 
00374       RESET_AUTO_PTR(pTrailerFieldNode, pTrailerFieldNode->getNextSiblingNode());
00375     }
00376   }
00377 
00378   // MSGTYPE
00379   DOMNodePtr pMessagesNode = pDoc->getNode("/fix/messages");
00380   if(!pMessagesNode.get())
00381     throw ConfigError("<messages> section not found in data dictionary");
00382 
00383   DOMNodePtr pMessageNode = pMessagesNode->getFirstChildNode();
00384   if(!pMessageNode.get()) throw ConfigError("No messages defined");
00385 
00386   while(pMessageNode.get())
00387   {
00388     if(pMessageNode->getName() == "message")
00389     {
00390       DOMAttributesPtr attrs = pMessageNode->getAttributes();
00391       std::string msgtype;
00392       if(!attrs->get("msgtype", msgtype))
00393         throw ConfigError("<field> does not have a name attribute");
00394       addMsgType(msgtype);
00395 
00396       std::string name;
00397       if(attrs->get("name", name))
00398         addValueName( 35, msgtype, name );
00399 
00400       DOMNodePtr pMessageFieldNode = pMessageNode->getFirstChildNode();
00401       while( pMessageFieldNode.get() )
00402       {
00403         if(pMessageFieldNode->getName() == "field"
00404            || pMessageFieldNode->getName() == "group")
00405         {
00406           DOMAttributesPtr attrs = pMessageFieldNode->getAttributes();
00407           std::string name;
00408           if(!attrs->get("name", name))
00409             throw ConfigError("<field> does not have a name attribute");
00410           int num = lookupXMLFieldNumber(pDoc.get(), name);
00411           addMsgField(msgtype, num);
00412 
00413           std::string required;
00414           if(attrs->get("required", required)
00415              && (required == "Y" || required == "y"))
00416           {
00417             addRequiredField(msgtype, num);
00418           }
00419         }
00420         else if(pMessageFieldNode->getName() == "component")
00421         {
00422           DOMAttributesPtr attrs = pMessageFieldNode->getAttributes();
00423           std::string required;
00424           attrs->get("required", required);
00425           bool isRequired = (required == "Y" || required == "y");
00426           addXMLComponentFields(pDoc.get(), pMessageFieldNode.get(),
00427                                 msgtype, *this, isRequired);
00428         }
00429         if(pMessageFieldNode->getName() == "group")
00430         {
00431           DOMAttributesPtr attrs = pMessageFieldNode->getAttributes();
00432           std::string required;
00433           attrs->get("required", required);
00434           bool isRequired = (required == "Y" || required == "y");
00435           addXMLGroup(pDoc.get(), pMessageFieldNode.get(), msgtype, *this, isRequired);
00436         }
00437         RESET_AUTO_PTR(pMessageFieldNode,
00438                        pMessageFieldNode->getNextSiblingNode());
00439       }
00440     }
00441     RESET_AUTO_PTR(pMessageNode, pMessageNode->getNextSiblingNode());
00442   }
00443 }
00444 
00445 message_order const& DataDictionary::getOrderedFields() const
00446 {
00447   if( m_orderedFieldsArray ) return m_orderedFieldsArray;
00448 
00449   int * tmp = new int[m_orderedFields.size() + 1];
00450   int * i = tmp;
00451 
00452   OrderedFields::const_iterator iter;
00453   for( iter = m_orderedFields.begin(); iter != m_orderedFields.end(); *(i++) = *(iter++) ) {}
00454   *i = 0;
00455 
00456   m_orderedFieldsArray = message_order(tmp);
00457   delete [] tmp;
00458 
00459   return m_orderedFieldsArray;
00460 }
00461 
00462 int DataDictionary::lookupXMLFieldNumber( DOMDocument* pDoc, DOMNode* pNode ) const
00463 {
00464   DOMAttributesPtr attrs = pNode->getAttributes();
00465   std::string name;
00466   if(!attrs->get("name", name))
00467     throw ConfigError("No name given to field");
00468   return lookupXMLFieldNumber( pDoc, name );
00469 }
00470 
00471 int DataDictionary::lookupXMLFieldNumber
00472 ( DOMDocument* pDoc, const std::string& name ) const
00473 {
00474   NameToField::const_iterator i = m_names.find(name);
00475   if( i == m_names.end() )
00476     throw ConfigError("Field " + name + " not defined in fields section");
00477   return i->second;
00478 }
00479 
00480 int DataDictionary::addXMLComponentFields( DOMDocument* pDoc, DOMNode* pNode,
00481                                             const std::string& msgtype,
00482                                             DataDictionary& DD,
00483                                             bool componentRequired )
00484 {
00485   int firstField = 0;
00486 
00487   DOMAttributesPtr attrs = pNode->getAttributes();
00488   std::string name;
00489   if(!attrs->get("name", name))
00490     throw ConfigError("No name given to component");
00491 
00492   DOMNodePtr pComponentNode =
00493     pDoc->getNode("/fix/components/component[@name='" + name + "']");
00494   if(pComponentNode.get() == 0)
00495     throw ConfigError("Component not found");
00496 
00497   DOMNodePtr pComponentFieldNode = pComponentNode->getFirstChildNode();
00498   while(pComponentFieldNode.get())
00499   {
00500     if(pComponentFieldNode->getName() == "field"
00501        || pComponentFieldNode->getName() == "group")
00502     {
00503       DOMAttributesPtr attrs = pComponentFieldNode->getAttributes();
00504       std::string name;
00505       if(!attrs->get("name", name))
00506         throw ConfigError("No name given to field");
00507       int field = lookupXMLFieldNumber(pDoc, name);
00508       if( firstField == 0 ) firstField = field;
00509 
00510       std::string required;
00511       if(attrs->get("required", required)
00512          && (required == "Y" || required =="y")
00513          && componentRequired)
00514       {
00515         addRequiredField(msgtype, field);
00516       }
00517 
00518       DD.addField(field);
00519       DD.addMsgField(msgtype, field);
00520     }
00521     if(pComponentFieldNode->getName() == "component")
00522     {
00523       DOMAttributesPtr attrs = pComponentFieldNode->getAttributes();
00524       std::string required;
00525       attrs->get("required", required);
00526       bool isRequired = (required == "Y" || required == "y");
00527       addXMLComponentFields(pDoc, pComponentFieldNode.get(),
00528                             msgtype, DD, isRequired);
00529     }
00530     if(pComponentFieldNode->getName() == "group")
00531     {
00532       DOMAttributesPtr attrs = pComponentFieldNode->getAttributes();
00533       std::string required;
00534       attrs->get("required", required);
00535       bool isRequired = (required == "Y" || required == "y");
00536       addXMLGroup(pDoc, pComponentFieldNode.get(), msgtype, DD, isRequired);
00537     }
00538     RESET_AUTO_PTR(pComponentFieldNode,
00539       pComponentFieldNode->getNextSiblingNode());
00540   }
00541   return firstField;
00542 }
00543 
00544 void DataDictionary::addXMLGroup( DOMDocument* pDoc, DOMNode* pNode,
00545                                   const std::string& msgtype,
00546                                   DataDictionary& DD, bool groupRequired  )
00547 {
00548   DOMAttributesPtr attrs = pNode->getAttributes();
00549   std::string name;
00550   if(!attrs->get("name", name))
00551     throw ConfigError("No name given to group");
00552   int group = lookupXMLFieldNumber( pDoc, name );
00553   int delim = 0;
00554   int field = 0;
00555   DataDictionary groupDD;
00556   DOMNodePtr node = pNode->getFirstChildNode();
00557   while(node.get())
00558   {
00559     if( node->getName() == "field" )
00560     {
00561       field = lookupXMLFieldNumber( pDoc, node.get() );
00562       groupDD.addField( field );
00563 
00564       DOMAttributesPtr attrs = node->getAttributes();
00565       std::string required;
00566       if( attrs->get("required", required)
00567          && ( required == "Y" || required =="y" )
00568          && groupRequired )
00569       {
00570         groupDD.addRequiredField(msgtype, field);
00571       }
00572     }
00573     else if( node->getName() == "component" )
00574     {
00575       field = addXMLComponentFields( pDoc, node.get(), msgtype, groupDD, false );
00576     }
00577     else if( node->getName() == "group" )
00578     {
00579       field = lookupXMLFieldNumber( pDoc, node.get() );
00580       groupDD.addField( field );
00581       DOMAttributesPtr attrs = node->getAttributes();
00582       std::string required;
00583       if( attrs->get("required", required )
00584          && ( required == "Y" || required =="y" )
00585          && groupRequired)
00586       {
00587         groupDD.addRequiredField(msgtype, field);
00588       }
00589       bool isRequired = false;
00590       if( attrs->get("required", required) )
00591       isRequired = (required == "Y" || required == "y");
00592       addXMLGroup( pDoc, node.get(), msgtype, groupDD, isRequired );
00593     }
00594     if( delim == 0 ) delim = field;
00595     RESET_AUTO_PTR(node, node->getNextSiblingNode());
00596   }
00597 
00598   if( delim ) DD.addGroup( msgtype, group, delim, groupDD );
00599 }
00600 
00601 TYPE::Type DataDictionary::XMLTypeToType( const std::string& type ) const
00602 {
00603   if ( m_beginString < "FIX.4.2" && type == "CHAR" )
00604     return TYPE::String;
00605 
00606   if ( type == "STRING" ) return TYPE::String;
00607   if ( type == "CHAR" ) return TYPE::Char;
00608   if ( type == "PRICE" ) return TYPE::Price;
00609   if ( type == "INT" ) return TYPE::Int;
00610   if ( type == "AMT" ) return TYPE::Amt;
00611   if ( type == "QTY" ) return TYPE::Qty;
00612   if ( type == "CURRENCY" ) return TYPE::Currency;
00613   if ( type == "MULTIPLEVALUESTRING" ) return TYPE::MultipleValueString;
00614   if ( type == "MULTIPLESTRINGVALUE" ) return TYPE::MultipleStringValue;
00615   if ( type == "MULTIPLECHARVALUE" ) return TYPE::MultipleCharValue;
00616   if ( type == "EXCHANGE" ) return TYPE::Exchange;
00617   if ( type == "UTCTIMESTAMP" ) return TYPE::UtcTimeStamp;
00618   if ( type == "BOOLEAN" ) return TYPE::Boolean;
00619   if ( type == "LOCALMKTDATE" ) return TYPE::LocalMktDate;
00620   if ( type == "DATA" ) return TYPE::Data;
00621   if ( type == "FLOAT" ) return TYPE::Float;
00622   if ( type == "PRICEOFFSET" ) return TYPE::PriceOffset;
00623   if ( type == "MONTHYEAR" ) return TYPE::MonthYear;
00624   if ( type == "DAYOFMONTH" ) return TYPE::DayOfMonth;
00625   if ( type == "UTCDATE" ) return TYPE::UtcDate;
00626   if ( type == "UTCDATEONLY" ) return TYPE::UtcDateOnly;
00627   if ( type == "UTCTIMEONLY" ) return TYPE::UtcTimeOnly;
00628   if ( type == "NUMINGROUP" ) return TYPE::NumInGroup;
00629   if ( type == "PERCENTAGE" ) return TYPE::Percentage;
00630   if ( type == "SEQNUM" ) return TYPE::SeqNum;
00631   if ( type == "LENGTH" ) return TYPE::Length;
00632   if ( type == "COUNTRY" ) return TYPE::Country;
00633   if ( type == "TIME" ) return TYPE::UtcTimeStamp;
00634   return TYPE::Unknown;
00635 }
00636 }

Generated on Mon Jun 23 2014 23:49:37 for QuickFIX by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2001