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

Generated on Mon Sep 15 2014 01:23:54 for QuickFIX by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2001