DataDictionary.h
Go to the documentation of this file.
00001 /* -*- C++ -*- */
00002 
00003 /****************************************************************************
00004 ** Copyright (c) 2001-2014
00005 **
00006 ** This file is part of the QuickFIX FIX Engine
00007 **
00008 ** This file may be distributed under the terms of the quickfixengine.org
00009 ** license as defined by quickfixengine.org and appearing in the file
00010 ** LICENSE included in the packaging of this file.
00011 **
00012 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00013 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00014 **
00015 ** See http://www.quickfixengine.org/LICENSE for licensing information.
00016 **
00017 ** Contact ask@quickfixengine.org if any conditions of this licensing are
00018 ** not clear to you.
00019 **
00020 ****************************************************************************/
00021 
00022 #ifndef FIX_DATADICTIONARY_H
00023 #define FIX_DATADICTIONARY_H
00024 
00025 #ifdef _MSC_VER
00026 #pragma warning( disable : 4503 4355 4786 4290 )
00027 #endif
00028 
00029 #include "Fields.h"
00030 #include "FieldMap.h"
00031 #include "DOMDocument.h"
00032 #include "Exceptions.h"
00033 #include <set>
00034 #include <map>
00035 #include <string.h>
00036 
00037 namespace FIX
00038 {
00039 class FieldMap;
00040 class Message;
00041 
00049 class DataDictionary
00050 {
00051   typedef std::set < int > MsgFields;
00052   typedef std::map < std::string, MsgFields > MsgTypeToField;
00053   typedef std::set < std::string > MsgTypes;
00054   typedef std::set < int > Fields;
00055   typedef std::map < int, bool > NonBodyFields;
00056   typedef std::vector< int > OrderedFields;
00057   typedef message_order OrderedFieldsArray;
00058   typedef std::map < int, TYPE::Type > FieldTypes;
00059   typedef std::set < std::string > Values;
00060   typedef std::map < int, Values > FieldToValue;
00061   typedef std::map < int, std::string > FieldToName;
00062   typedef std::map < std::string, int > NameToField;
00063   typedef std::map < std::pair < int, std::string > , std::string  > ValueToName;
00064   // while FieldToGroup structure seems to be overcomplicated
00065   // in reality it yields a lot of performance because:
00066   // 1) avoids memory copying;
00067   // 2) first lookup is done by comparing integers and not string objects
00068   // TODO: use hash_map with good hashing algorithm
00069   typedef std::map < std::string, std::pair < int, DataDictionary* > > FieldPresenceMap;
00070   typedef std::map < int, FieldPresenceMap > FieldToGroup;
00071 
00072 public:
00073   DataDictionary();
00074   DataDictionary( const DataDictionary& copy );
00075   DataDictionary( std::istream& stream ) throw( ConfigError );
00076   DataDictionary( const std::string& url ) throw( ConfigError );
00077   virtual ~DataDictionary();
00078 
00079   void readFromURL( const std::string& url ) throw( ConfigError );
00080   void readFromDocument( DOMDocumentPtr pDoc ) throw( ConfigError );
00081   void readFromStream( std::istream& stream ) throw( ConfigError );
00082 
00083   message_order const& getOrderedFields() const;
00084 
00085   // storage functions
00086   void setVersion( const std::string& beginString )
00087   {
00088     m_beginString = beginString;
00089     m_hasVersion = true;
00090   }
00091   std::string getVersion() const
00092   {
00093     return m_beginString.getString();
00094   }
00095 
00096   void addField( int field )
00097   {
00098     m_fields.insert( field );
00099     m_orderedFields.push_back( field );
00100   }
00101 
00102   void addFieldName( int field, const std::string& name )
00103   {
00104     if( m_names.insert( std::make_pair(name, field) ).second == false )
00105       throw ConfigError( "Field named " + name + " defined multiple times" );
00106     m_fieldNames[field] = name;
00107   }
00108 
00109   bool getFieldName( int field, std::string& name ) const
00110   {
00111     FieldToName::const_iterator i = m_fieldNames.find( field );
00112     if(i == m_fieldNames.end()) return false;
00113     name = i->second;
00114     return true;
00115   }
00116 
00117   bool getFieldTag( const std::string& name, int& field ) const
00118   {
00119     NameToField::const_iterator i = m_names.find( name );
00120     if(i == m_names.end()) return false;
00121     field = i->second;
00122     return true;
00123   }
00124 
00125   void addValueName( int field, const std::string& value, const std::string& name )
00126   {
00127     m_valueNames[std::make_pair(field, value)] = name;
00128   }
00129 
00130   bool getValueName( int field, const std::string& value, std::string& name ) const
00131   {
00132     ValueToName::const_iterator i = m_valueNames.find( std::make_pair(field, value) );
00133     if(i == m_valueNames.end()) return false;
00134     name = i->second;
00135     return true;
00136   }
00137 
00138   bool isField( int field ) const
00139   {
00140     return m_fields.find( field ) != m_fields.end();
00141   }
00142 
00143   void addMsgType( const std::string& msgType )
00144   {
00145     m_messages.insert( msgType );
00146   }
00147 
00148   bool isMsgType( const std::string& msgType ) const
00149   {
00150     return m_messages.find( msgType ) != m_messages.end();
00151   }
00152 
00153   void addMsgField( const std::string& msgType, int field )
00154   {
00155     m_messageFields[ msgType ].insert( field );
00156   }
00157 
00158   bool isMsgField( const std::string& msgType, int field ) const
00159   {
00160     MsgTypeToField::const_iterator i = m_messageFields.find( msgType );
00161     if ( i == m_messageFields.end() ) return false;
00162     return i->second.find( field ) != i->second.end();
00163   }
00164 
00165   void addHeaderField( int field, bool required )
00166   {
00167     m_headerFields[ field ] = required;
00168   }
00169 
00170   bool isHeaderField( int field ) const
00171   {
00172     return m_headerFields.find( field ) != m_headerFields.end();
00173   }
00174 
00175   void addTrailerField( int field, bool required )
00176   {
00177     m_trailerFields[ field ] = required;
00178   }
00179 
00180   bool isTrailerField( int field ) const
00181   {
00182     return m_trailerFields.find( field ) != m_trailerFields.end();
00183   }
00184 
00185   void addFieldType( int field, FIX::TYPE::Type type )
00186   {
00187     m_fieldTypes[ field ] = type;
00188 
00189     if( type == FIX::TYPE::Data )
00190       m_dataFields.insert( field );
00191   }
00192 
00193   bool getFieldType( int field, FIX::TYPE::Type& type ) const
00194   {
00195     FieldTypes::const_iterator i = m_fieldTypes.find( field );
00196     if ( i == m_fieldTypes.end() ) return false;
00197     type = i->second;
00198     return true;
00199   }
00200 
00201   void addRequiredField( const std::string& msgType, int field )
00202   {
00203     m_requiredFields[ msgType ].insert( field );
00204   }
00205 
00206   bool isRequiredField( const std::string& msgType, int field ) const
00207   {
00208     MsgTypeToField::const_iterator i = m_requiredFields.find( msgType );
00209     if ( i == m_requiredFields.end() ) return false;
00210     return i->second.find( field ) != i->second.end();
00211   }
00212 
00213   void addFieldValue( int field, const std::string& value )
00214   {
00215     m_fieldValues[ field ].insert( value );
00216   }
00217 
00218   bool hasFieldValue( int field ) const
00219   {
00220     FieldToValue::const_iterator i = m_fieldValues.find( field );
00221     return i != m_fieldValues.end();
00222   }
00223 
00224   bool isFieldValue( int field, const std::string& value ) const
00225   {
00226     FieldToValue::const_iterator i = m_fieldValues.find( field );
00227     if ( i == m_fieldValues.end() )
00228       return false;
00229     if( !isMultipleValueField( field ) )
00230       return i->second.find( value ) != i->second.end();
00231 
00232     // MultipleValue
00233     std::string::size_type startPos = 0;
00234     std::string::size_type endPos = 0;
00235     do
00236     {
00237       endPos = value.find_first_of(' ', startPos);
00238       std::string singleValue =
00239         value.substr( startPos, endPos - startPos );
00240       if( i->second.find( singleValue ) == i->second.end() )
00241         return false;
00242       startPos = endPos + 1;
00243     } while( endPos != std::string::npos );
00244     return true;
00245   }
00246 
00247   void addGroup( const std::string& msg, int field, int delim,
00248                  const DataDictionary& dataDictionary )
00249   {
00250     DataDictionary * pDD = new DataDictionary( dataDictionary );
00251     pDD->setVersion( getVersion() );
00252 
00253     FieldPresenceMap& presenceMap = m_groups[ field ];
00254     presenceMap[ msg ] = std::make_pair( delim, pDD );
00255   }
00256 
00257   bool isGroup( const std::string& msg, int field ) const
00258   {
00259     FieldToGroup::const_iterator i = m_groups.find( field );
00260     if ( i == m_groups.end() ) return false;
00261 
00262     const FieldPresenceMap& presenceMap = i->second;
00263 
00264     FieldPresenceMap::const_iterator iter = presenceMap.find( msg );
00265     return ( iter != presenceMap.end() );
00266   }
00267 
00268   bool getGroup( const std::string& msg, int field, int& delim,
00269                  const DataDictionary*& pDataDictionary ) const
00270   {
00271     FieldToGroup::const_iterator i = m_groups.find( field );
00272     if ( i == m_groups.end() ) return false;
00273 
00274     const FieldPresenceMap& presenceMap = i->second;
00275 
00276     FieldPresenceMap::const_iterator iter = presenceMap.find( msg );
00277     if( iter == presenceMap.end() ) return false;
00278 
00279     std::pair < int, DataDictionary* > pair = iter->second;
00280     delim = pair.first;
00281     pDataDictionary = pair.second;
00282     return true;
00283   }
00284 
00285   bool isDataField( int field ) const
00286   {
00287     MsgFields::const_iterator iter = m_dataFields.find( field );
00288     return iter != m_dataFields.end();
00289   }
00290 
00291   bool isMultipleValueField( int field ) const
00292   {
00293     FieldTypes::const_iterator i = m_fieldTypes.find( field );
00294     return i != m_fieldTypes.end() 
00295       && (i->second == TYPE::MultipleValueString 
00296           || i->second == TYPE::MultipleCharValue 
00297           || i->second == TYPE::MultipleStringValue );
00298   }
00299 
00300   void checkFieldsOutOfOrder( bool value )
00301   { m_checkFieldsOutOfOrder = value; }
00302   void checkFieldsHaveValues( bool value )
00303   { m_checkFieldsHaveValues = value; }
00304   void checkUserDefinedFields( bool value )
00305   { m_checkUserDefinedFields = value; }
00306 
00308   static void validate( const Message& message,
00309                         const DataDictionary* const pSessionDD,
00310                         const DataDictionary* const pAppID ) throw( FIX::Exception );
00311 
00312   void validate( const Message& message ) const throw ( FIX::Exception )
00313   { validate( message, false ); }
00314   void validate( const Message& message, bool bodyOnly ) const throw( FIX::Exception )
00315   { validate( message, bodyOnly ? (DataDictionary*)0 : this, this ); }
00316 
00317   DataDictionary& operator=( const DataDictionary& rhs );
00318 
00319 private:
00321   void iterate( const FieldMap& map, const MsgType& msgType ) const;
00322 
00324   void checkMsgType( const MsgType& msgType ) const
00325   {
00326     if ( !isMsgType( msgType.getValue() ) )
00327       throw InvalidMessageType();
00328   }
00329 
00331   bool shouldCheckTag( const FieldBase& field ) const
00332   {
00333     if( !m_checkUserDefinedFields && field.getField() >= FIELD::UserMin )
00334       return false;
00335     else
00336       return true;
00337   }
00338 
00340   void checkValidTagNumber( const FieldBase& field ) const
00341   throw( InvalidTagNumber )
00342   {
00343     if( m_fields.find( field.getField() ) == m_fields.end() )
00344       throw InvalidTagNumber( field.getField() );
00345   }
00346 
00347   void checkValidFormat( const FieldBase& field ) const
00348   throw( IncorrectDataFormat )
00349   {
00350     try
00351     {
00352       TYPE::Type type = TYPE::Unknown;
00353       getFieldType( field.getField(), type );
00354       switch ( type )
00355       {
00356       case TYPE::String:
00357         STRING_CONVERTOR::convert( field.getString() ); break;
00358       case TYPE::Char:
00359         CHAR_CONVERTOR::convert( field.getString() ); break;
00360       case TYPE::Price:
00361         PRICE_CONVERTOR::convert( field.getString() ); break;
00362       case TYPE::Int:
00363         INT_CONVERTOR::convert( field.getString() ); break;
00364       case TYPE::Amt:
00365         AMT_CONVERTOR::convert( field.getString() ); break;
00366       case TYPE::Qty:
00367         QTY_CONVERTOR::convert( field.getString() ); break;
00368       case TYPE::Currency:
00369         CURRENCY_CONVERTOR::convert( field.getString() ); break;
00370       case TYPE::MultipleValueString:
00371         MULTIPLEVALUESTRING_CONVERTOR::convert( field.getString() ); break;
00372       case TYPE::MultipleStringValue:
00373         MULTIPLESTRINGVALUE_CONVERTOR::convert( field.getString() ); break;
00374       case TYPE::MultipleCharValue:
00375         MULTIPLECHARVALUE_CONVERTOR::convert( field.getString() ); break;
00376       case TYPE::Exchange:
00377         EXCHANGE_CONVERTOR::convert( field.getString() ); break;
00378       case TYPE::UtcTimeStamp:
00379         UTCTIMESTAMP_CONVERTOR::convert( field.getString() ); break;
00380       case TYPE::Boolean:
00381         BOOLEAN_CONVERTOR::convert( field.getString() ); break;
00382       case TYPE::LocalMktDate:
00383         LOCALMKTDATE_CONVERTOR::convert( field.getString() ); break;
00384       case TYPE::Data:
00385         DATA_CONVERTOR::convert( field.getString() ); break;
00386       case TYPE::Float:
00387         FLOAT_CONVERTOR::convert( field.getString() ); break;
00388       case TYPE::PriceOffset:
00389         PRICEOFFSET_CONVERTOR::convert( field.getString() ); break;
00390       case TYPE::MonthYear:
00391         MONTHYEAR_CONVERTOR::convert( field.getString() ); break;
00392       case TYPE::DayOfMonth:
00393         DAYOFMONTH_CONVERTOR::convert( field.getString() ); break;
00394       case TYPE::UtcDate:
00395         UTCDATE_CONVERTOR::convert( field.getString() ); break;
00396       case TYPE::UtcTimeOnly:
00397         UTCTIMEONLY_CONVERTOR::convert( field.getString() ); break;
00398       case TYPE::NumInGroup:
00399         NUMINGROUP_CONVERTOR::convert( field.getString() ); break;
00400       case TYPE::Percentage:
00401         PERCENTAGE_CONVERTOR::convert( field.getString() ); break;
00402       case TYPE::SeqNum:
00403         SEQNUM_CONVERTOR::convert( field.getString() ); break;
00404       case TYPE::Length:
00405         LENGTH_CONVERTOR::convert( field.getString() ); break;
00406       case TYPE::Country:
00407         COUNTRY_CONVERTOR::convert( field.getString() ); break;
00408       case TYPE::TzTimeOnly:
00409         TZTIMEONLY_CONVERTOR::convert( field.getString() ); break;
00410       case TYPE::TzTimeStamp:
00411         TZTIMESTAMP_CONVERTOR::convert( field.getString() ); break;
00412       case TYPE::XmlData:
00413         XMLDATA_CONVERTOR::convert( field.getString() ); break;
00414       case TYPE::Language:
00415         LANGUAGE_CONVERTOR::convert( field.getString() ); break;
00416       case TYPE::Unknown: break;
00417       }
00418     }
00419     catch ( FieldConvertError& )
00420     { throw IncorrectDataFormat( field.getField(), field.getString() ); }
00421   }
00422 
00423   void checkValue( const FieldBase& field ) const
00424   throw( IncorrectTagValue )
00425   {
00426     if ( !hasFieldValue( field.getField() ) ) return ;
00427 
00428     const std::string& value = field.getString();
00429     if ( !isFieldValue( field.getField(), value ) )
00430       throw IncorrectTagValue( field.getField() );
00431   }
00432 
00434   void checkHasValue( const FieldBase& field ) const
00435   throw( NoTagValue )
00436   {
00437     if ( m_checkFieldsHaveValues && !field.getString().length() )
00438       throw NoTagValue( field.getField() );
00439   }
00440 
00442   void checkIsInMessage
00443   ( const FieldBase& field, const MsgType& msgType ) const
00444   throw( TagNotDefinedForMessage )
00445   {
00446     if ( !isMsgField( msgType, field.getField() ) )
00447       throw TagNotDefinedForMessage( field.getField() );
00448   }
00449 
00451   void checkGroupCount
00452   ( const FieldBase& field, const FieldMap& fieldMap, const MsgType& msgType ) const
00453   throw( RepeatingGroupCountMismatch )
00454   {
00455     int fieldNum = field.getField();
00456     if( isGroup(msgType, fieldNum) )
00457     {
00458       if( (int)fieldMap.groupCount(fieldNum)
00459         != IntConvertor::convert(field.getString()) )
00460       throw RepeatingGroupCountMismatch(fieldNum);
00461     }
00462   }
00463 
00465   void checkHasRequired
00466   ( const FieldMap& header, const FieldMap& body, const FieldMap& trailer,
00467     const MsgType& msgType ) const
00468   throw( RequiredTagMissing )
00469   {
00470     NonBodyFields::const_iterator iNBF;
00471     for( iNBF = m_headerFields.begin(); iNBF != m_headerFields.end(); ++iNBF )
00472     {
00473       if( iNBF->second == true && !header.isSetField(iNBF->first) )
00474         throw RequiredTagMissing( iNBF->first );
00475     }
00476 
00477     for( iNBF = m_trailerFields.begin(); iNBF != m_trailerFields.end(); ++iNBF )
00478     {
00479       if( iNBF->second == true && !trailer.isSetField(iNBF->first) )
00480         throw RequiredTagMissing( iNBF->first );
00481     }
00482 
00483     MsgTypeToField::const_iterator iM
00484       = m_requiredFields.find( msgType.getString() );
00485     if ( iM == m_requiredFields.end() ) return ;
00486 
00487     const MsgFields& fields = iM->second;
00488     MsgFields::const_iterator iF;
00489     for( iF = fields.begin(); iF != fields.end(); ++iF )
00490     {
00491       if( !body.isSetField(*iF) )
00492         throw RequiredTagMissing( *iF );
00493     }
00494 
00495     FieldMap::g_iterator groups;
00496     for( groups = body.g_begin(); groups != body.g_end(); ++groups )
00497     {
00498       int delim;
00499       const DataDictionary* DD = 0;
00500       int field = groups->first;
00501       if( getGroup( msgType.getValue(), field, delim, DD ) )
00502       {
00503         std::vector<FieldMap*>::const_iterator group;
00504         for( group = groups->second.begin(); group != groups->second.end(); ++group )
00505           DD->checkHasRequired( **group, **group, **group, msgType );
00506       }
00507     }
00508   }
00509 
00510   int lookupXMLFieldNumber( DOMDocument*, DOMNode* ) const;
00511   int lookupXMLFieldNumber( DOMDocument*, const std::string& name ) const;
00512   int addXMLComponentFields( DOMDocument*, DOMNode*, const std::string& msgtype, DataDictionary&, bool );
00513   void addXMLGroup( DOMDocument*, DOMNode*, const std::string& msgtype, DataDictionary&, bool );
00514   TYPE::Type XMLTypeToType( const std::string& xmlType ) const;
00515 
00516   bool m_hasVersion;
00517   bool m_checkFieldsOutOfOrder;
00518   bool m_checkFieldsHaveValues;
00519   bool m_checkUserDefinedFields;
00520   BeginString m_beginString;
00521   MsgTypeToField m_messageFields;
00522   MsgTypeToField m_requiredFields;
00523   MsgTypes m_messages;
00524   Fields m_fields;
00525   OrderedFields m_orderedFields;
00526   mutable OrderedFieldsArray m_orderedFieldsArray;
00527   NonBodyFields m_headerFields;
00528   NonBodyFields m_trailerFields;
00529   FieldTypes m_fieldTypes;
00530   FieldToValue m_fieldValues;
00531   FieldToName m_fieldNames;
00532   NameToField m_names;
00533   ValueToName m_valueNames;
00534   FieldToGroup m_groups;
00535   MsgFields m_dataFields;
00536 };
00537 }
00538 
00539 #endif //FIX_DATADICTIONARY_H

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