QuickFIX: /home/omiller/Development/autobuild/quickfix/src/C++/DataDictionary.h Source File

Index Source Files Annotated Class List Alphabetical Class List Class Hierarchy Graphical Class Hierarchy

# DataDictionary.h

Go to the documentation of this file.

    00001 /* -*- C++ -*- */
    00002
    00003 /****************************************************************************
    00004 ** Copyright (c) quickfixengine.org  All rights reserved.
    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 int* 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 > ,
    00064   std::string  > ValueToName;
    00065   typedef std::map < std::pair < std::string, int > ,
    00066   std::pair < int, DataDictionary* > > FieldToGroup;
    00067
    00068 public:
    00069   DataDictionary();
    00070   DataDictionary( const DataDictionary& copy );
    00071   DataDictionary( std::istream& stream ) throw( ConfigError );
    00072   DataDictionary( const std::string& url ) throw( ConfigError );
    00073   virtual ~DataDictionary();
    00074
    00075   void readFromURL( const std::string& url ) throw( ConfigError );
    00076   void readFromDocument( DOMDocumentPtr pDoc ) throw( ConfigError );
    00077   void readFromStream( std::istream& stream ) throw( ConfigError );
    00078
    00079   int* getOrderedFields() const;
    00080
    00081   // storage functions
    00082   void setVersion( const std::string& beginString )
    00083   {
    00084     m_beginString = beginString;
    00085     m_hasVersion = true;
    00086   }
    00087   std::string getVersion() const
    00088   {
    00089     return m_beginString.getString();
    00090   }
    00091
    00092   void addField( int field )
    00093   {
    00094     m_fields.insert( field );
    00095     m_orderedFields.push_back( field );
    00096   }
    00097
    00098   void addFieldName( int field, const std::string& name )
    00099   {
    00100     if( m_names.insert( std::make_pair(name, field) ).second == false )
    00101       throw ConfigError( "Field named " + name + " defined multiple times" );
    00102     m_fieldNames[field] = name;
    00103   }
    00104
    00105   bool getFieldName( int field, std::string& name ) const
    00106   {
    00107     FieldToName::const_iterator i = m_fieldNames.find( field );
    00108     if(i == m_fieldNames.end()) return false;
    00109     name = i->second;
    00110     return true;
    00111   }
    00112
    00113   bool getFieldTag( std::string name, int& field ) const
    00114   {
    00115     NameToField::const_iterator i = m_names.find( name );
    00116     if(i == m_names.end()) return false;
    00117     field = i->second;
    00118     return true;
    00119   }
    00120
    00121   void addValueName( int field, const std::string& value, const std::string& name )
    00122   {
    00123     m_valueNames[std::make_pair(field, value)] = name;
    00124   }
    00125
    00126   bool getValueName( int field, const std::string& value, std::string& name ) const
    00127   {
    00128     ValueToName::const_iterator i = m_valueNames.find( std::make_pair(field, value) );
    00129     if(i == m_valueNames.end()) return false;
    00130     name = i->second;
    00131     return true;
    00132   }
    00133
    00134   bool isField( int field ) const
    00135   {
    00136     return m_fields.find( field ) != m_fields.end();
    00137   }
    00138
    00139   void addMsgType( const std::string& msgType )
    00140   {
    00141     m_messages.insert( msgType );
    00142   }
    00143
    00144   bool isMsgType( const std::string& msgType ) const
    00145   {
    00146     return m_messages.find( msgType ) != m_messages.end();
    00147   }
    00148
    00149   void addMsgField( const std::string& msgType, int field )
    00150   {
    00151     m_messageFields[ msgType ].insert( field );
    00152   }
    00153
    00154   bool isMsgField( const std::string& msgType, int field ) const
    00155   {
    00156     MsgTypeToField::const_iterator i = m_messageFields.find( msgType );
    00157     if ( i == m_messageFields.end() ) return false;
    00158     return i->second.find( field ) != i->second.end();
    00159   }
    00160
    00161   void addHeaderField( int field, bool required )
    00162   {
    00163     m_headerFields[ field ] = required;
    00164   }
    00165
    00166   bool isHeaderField( int field ) const
    00167   {
    00168     return m_headerFields.find( field ) != m_headerFields.end();
    00169   }
    00170
    00171   void addTrailerField( int field, bool required )
    00172   {
    00173     m_trailerFields[ field ] = required;
    00174   }
    00175
    00176   bool isTrailerField( int field ) const
    00177   {
    00178     return m_trailerFields.find( field ) != m_trailerFields.end();
    00179   }
    00180
    00181   void addFieldType( int field, FIX::TYPE::Type type )
    00182   {
    00183     m_fieldTypes[ field ] = type;
    00184   }
    00185
    00186   bool getFieldType( int field, FIX::TYPE::Type& type ) const
    00187   {
    00188     FieldTypes::const_iterator i = m_fieldTypes.find( field );
    00189     if ( i == m_fieldTypes.end() ) return false;
    00190     type = i->second;
    00191     return true;
    00192   }
    00193
    00194   void addRequiredField( const std::string& msgType, int field )
    00195   {
    00196     m_requiredFields[ msgType ].insert( field );
    00197   }
    00198
    00199   bool isRequiredField( const std::string& msgType, int field ) const
    00200   {
    00201     MsgTypeToField::const_iterator i = m_requiredFields.find( msgType );
    00202     if ( i == m_requiredFields.end() ) return false;
    00203     return i->second.find( field ) != i->second.end();
    00204   }
    00205
    00206   void addFieldValue( int field, const std::string& value )
    00207   {
    00208     m_fieldValues[ field ].insert( value );
    00209   }
    00210
    00211   bool hasFieldValue( int field ) const
    00212   {
    00213     FieldToValue::const_iterator i = m_fieldValues.find( field );
    00214     return i != m_fieldValues.end();
    00215   }
    00216
    00217   bool isFieldValue( int field, const std::string& value ) const
    00218   {
    00219     FieldToValue::const_iterator i = m_fieldValues.find( field );
    00220     if ( i == m_fieldValues.end() )
    00221       return false;
    00222     if( !isMultipleValueField( field ) )
    00223       return i->second.find( value ) != i->second.end();
    00224
    00225     // MultipleValue
    00226     std::string::size_type startPos = 0;
    00227     std::string::size_type endPos = 0;
    00228     do
    00229     {
    00230       endPos = value.find_first_of(' ', startPos);
    00231       std::string singleValue =
    00232         value.substr( startPos, endPos - startPos );
    00233       if( i->second.find( singleValue ) == i->second.end() )
    00234         return false;
    00235       startPos = endPos + 1;
    00236     } while( endPos != std::string::npos );
    00237     return true;
    00238   }
    00239
    00240   void addGroup( const std::string& msg, int field, int delim,
    00241                  const DataDictionary& dataDictionary )
    00242   {
    00243     DataDictionary * pDD = new DataDictionary;
    00244     *pDD = dataDictionary;
    00245     pDD->setVersion( getVersion() );
    00246     m_groups[ std::make_pair( msg, field ) ] = std::make_pair( delim, pDD );
    00247   }
    00248
    00249   bool isGroup( const std::string& msg, int field ) const
    00250   {
    00251     return m_groups.find( std::make_pair( msg, field ) ) != m_groups.end();
    00252   }
    00253
    00254   bool getGroup( const std::string& msg, int field, int& delim,
    00255                  const DataDictionary*& pDataDictionary ) const
    00256   {
    00257     FieldToGroup::const_iterator i =
    00258       m_groups.find( std::make_pair( msg, field ) );
    00259     if ( i == m_groups.end() ) return false;
    00260     std::pair < int, DataDictionary* > pair = i->second;
    00261     delim = pair.first;
    00262     pDataDictionary = pair.second;
    00263     return true;
    00264   }
    00265
    00266   bool isDataField( int field ) const
    00267   {
    00268     FieldTypes::const_iterator i = m_fieldTypes.find( field );
    00269     return i != m_fieldTypes.end() && i->second == TYPE::Data;
    00270   }
    00271
    00272   bool isMultipleValueField( int field ) const
    00273   {
    00274     FieldTypes::const_iterator i = m_fieldTypes.find( field );
    00275     return i != m_fieldTypes.end()
    00276       && (i->second == TYPE::MultipleValueString
    00277           || i->second == TYPE::MultipleCharValue
    00278           || i->second == TYPE::MultipleStringValue );
    00279   }
    00280
    00281   void checkFieldsOutOfOrder( bool value )
    00282   { m_checkFieldsOutOfOrder = value; }
    00283   void checkFieldsHaveValues( bool value )
    00284   { m_checkFieldsHaveValues = value; }
    00285   void checkUserDefinedFields( bool value )
    00286   { m_checkUserDefinedFields = value; }
    00287
    00289   static void validate( const Message& message,
    00290                         const DataDictionary* const pSessionDD,
    00291                         const DataDictionary* const pAppID ) throw( FIX::Exception );
    00292
    00293   void validate( const Message& message ) const throw ( FIX::Exception )
    00294   { validate( message, false ); }
    00295   void validate( const Message& message, bool bodyOnly ) const throw( FIX::Exception )
    00296   { validate( message, bodyOnly ? (DataDictionary*)0 : this, this ); }
    00297
    00298   DataDictionary& operator=( const DataDictionary& rhs );
    00299
    00300 private:
    00302   void iterate( const FieldMap& map, const MsgType& msgType ) const;
    00303
    00305   void checkMsgType( const MsgType& msgType ) const
    00306   {
    00307     if ( !isMsgType( msgType.getValue() ) )
    00308       throw InvalidMessageType();
    00309   }
    00310
    00312   bool shouldCheckTag( const FieldBase& field ) const
    00313   {
    00314     if( !m_checkUserDefinedFields && field.getField() >= FIELD::UserMin )
    00315       return false;
    00316     else
    00317       return true;
    00318   }
    00319
    00321   void checkValidTagNumber( const FieldBase& field ) const
    00322   throw( InvalidTagNumber )
    00323   {
    00324     if( m_fields.find( field.getField() ) == m_fields.end() )
    00325       throw InvalidTagNumber( field.getField() );
    00326   }
    00327
    00328   void checkValidFormat( const FieldBase& field ) const
    00329   throw( IncorrectDataFormat )
    00330   {
    00331     try
    00332     {
    00333       TYPE::Type type = TYPE::Unknown;
    00334       getFieldType( field.getField(), type );
    00335       switch ( type )
    00336       {
    00337       case TYPE::String:
    00338         STRING_CONVERTOR::convert( field.getString() ); break;
    00339       case TYPE::Char:
    00340         CHAR_CONVERTOR::convert( field.getString() ); break;
    00341       case TYPE::Price:
    00342         PRICE_CONVERTOR::convert( field.getString() ); break;
    00343       case TYPE::Int:
    00344         INT_CONVERTOR::convert( field.getString() ); break;
    00345       case TYPE::Amt:
    00346         AMT_CONVERTOR::convert( field.getString() ); break;
    00347       case TYPE::Qty:
    00348         QTY_CONVERTOR::convert( field.getString() ); break;
    00349       case TYPE::Currency:
    00350         CURRENCY_CONVERTOR::convert( field.getString() ); break;
    00351       case TYPE::MultipleValueString:
    00352         MULTIPLEVALUESTRING_CONVERTOR::convert( field.getString() ); break;
    00353       case TYPE::MultipleStringValue:
    00354         MULTIPLESTRINGVALUE_CONVERTOR::convert( field.getString() ); break;
    00355       case TYPE::MultipleCharValue:
    00356         MULTIPLECHARVALUE_CONVERTOR::convert( field.getString() ); break;
    00357       case TYPE::Exchange:
    00358         EXCHANGE_CONVERTOR::convert( field.getString() ); break;
    00359       case TYPE::UtcTimeStamp:
    00360         UTCTIMESTAMP_CONVERTOR::convert( field.getString() ); break;
    00361       case TYPE::Boolean:
    00362         BOOLEAN_CONVERTOR::convert( field.getString() ); break;
    00363       case TYPE::LocalMktDate:
    00364         LOCALMKTDATE_CONVERTOR::convert( field.getString() ); break;
    00365       case TYPE::Data:
    00366         DATA_CONVERTOR::convert( field.getString() ); break;
    00367       case TYPE::Float:
    00368         FLOAT_CONVERTOR::convert( field.getString() ); break;
    00369       case TYPE::PriceOffset:
    00370         PRICEOFFSET_CONVERTOR::convert( field.getString() ); break;
    00371       case TYPE::MonthYear:
    00372         MONTHYEAR_CONVERTOR::convert( field.getString() ); break;
    00373       case TYPE::DayOfMonth:
    00374         DAYOFMONTH_CONVERTOR::convert( field.getString() ); break;
    00375       case TYPE::UtcDate:
    00376         UTCDATE_CONVERTOR::convert( field.getString() ); break;
    00377       case TYPE::UtcTimeOnly:
    00378         UTCTIMEONLY_CONVERTOR::convert( field.getString() ); break;
    00379       case TYPE::NumInGroup:
    00380         NUMINGROUP_CONVERTOR::convert( field.getString() ); break;
    00381       case TYPE::Percentage:
    00382         PERCENTAGE_CONVERTOR::convert( field.getString() ); break;
    00383       case TYPE::SeqNum:
    00384         SEQNUM_CONVERTOR::convert( field.getString() ); break;
    00385       case TYPE::Length:
    00386         LENGTH_CONVERTOR::convert( field.getString() ); break;
    00387       case TYPE::Country:
    00388         COUNTRY_CONVERTOR::convert( field.getString() ); break;
    00389       case TYPE::TzTimeOnly:
    00390         TZTIMEONLY_CONVERTOR::convert( field.getString() ); break;
    00391       case TYPE::TzTimeStamp:
    00392         TZTIMESTAMP_CONVERTOR::convert( field.getString() ); break;
    00393       case TYPE::XmlData:
    00394         XMLDATA_CONVERTOR::convert( field.getString() ); break;
    00395       case TYPE::Language:
    00396         LANGUAGE_CONVERTOR::convert( field.getString() ); break;
    00397       case TYPE::Unknown: break;
    00398       }
    00399     }
    00400     catch ( FieldConvertError& )
    00401     { throw IncorrectDataFormat( field.getField(), field.getString() ); }
    00402   }
    00403
    00404   void checkValue( const FieldBase& field ) const
    00405   throw( IncorrectTagValue )
    00406   {
    00407     if ( !hasFieldValue( field.getField() ) ) return ;
    00408
    00409     const std::string& value = field.getString();
    00410     if ( !isFieldValue( field.getField(), value ) )
    00411       throw IncorrectTagValue( field.getField() );
    00412   }
    00413
    00415   void checkHasValue( const FieldBase& field ) const
    00416   throw( NoTagValue )
    00417   {
    00418     if ( m_checkFieldsHaveValues && !field.getString().length() )
    00419       throw NoTagValue( field.getField() );
    00420   }
    00421
    00423   void checkIsInMessage
    00424   ( const FieldBase& field, const MsgType& msgType ) const
    00425   throw( TagNotDefinedForMessage )
    00426   {
    00427     if ( !isMsgField( msgType, field.getField() ) )
    00428       throw TagNotDefinedForMessage( field.getField() );
    00429   }
    00430
    00432   void checkGroupCount
    00433   ( const FieldBase& field, const FieldMap& fieldMap, const MsgType& msgType ) const
    00434   throw( RepeatingGroupCountMismatch )
    00435   {
    00436     int fieldNum = field.getField();
    00437     if( isGroup(msgType, fieldNum) )
    00438     {
    00439       if( fieldMap.groupCount(fieldNum)
    00440         != IntConvertor::convert(field.getString()) )
    00441       throw RepeatingGroupCountMismatch(fieldNum);
    00442     }
    00443   }
    00444
    00446   void checkHasRequired
    00447   ( const FieldMap& header, const FieldMap& body, const FieldMap& trailer,
    00448     const MsgType& msgType ) const
    00449   throw( RequiredTagMissing )
    00450   {
    00451     NonBodyFields::const_iterator iNBF;
    00452     for( iNBF = m_headerFields.begin(); iNBF != m_headerFields.end(); ++iNBF )
    00453     {
    00454       if( iNBF->second == true && !header.isSetField(iNBF->first) )
    00455         throw RequiredTagMissing( iNBF->first );
    00456     }
    00457
    00458     for( iNBF = m_trailerFields.begin(); iNBF != m_trailerFields.end(); ++iNBF )
    00459     {
    00460       if( iNBF->second == true && !trailer.isSetField(iNBF->first) )
    00461         throw RequiredTagMissing( iNBF->first );
    00462     }
    00463
    00464     MsgTypeToField::const_iterator iM
    00465       = m_requiredFields.find( msgType.getString() );
    00466     if ( iM == m_requiredFields.end() ) return ;
    00467
    00468     const MsgFields& fields = iM->second;
    00469     MsgFields::const_iterator iF;
    00470     for( iF = fields.begin(); iF != fields.end(); ++iF )
    00471     {
    00472       if( !body.isSetField(*iF) )
    00473         throw RequiredTagMissing( *iF );
    00474     }
    00475
    00476     FieldMap::g_iterator groups;
    00477     for( groups = body.g_begin(); groups != body.g_end(); ++groups )
    00478     {
    00479       int delim;
    00480       const DataDictionary* DD = 0;
    00481       int field = groups->first;
    00482       if( getGroup( msgType.getValue(), field, delim, DD ) )
    00483       {
    00484         std::vector<FieldMap*>::const_iterator group;
    00485         for( group = groups->second.begin(); group != groups->second.end(); ++group )
    00486           DD->checkHasRequired( **group, **group, **group, msgType );
    00487       }
    00488     }
    00489   }
    00490
    00492   void readMSXMLDOM( const std::string& );
    00493   void readMSXML( const std::string& );
    00495   void readLibXml( const std::string& );
    00496
    00497   int lookupXMLFieldNumber( DOMDocument*, DOMNode* ) const;
    00498   int lookupXMLFieldNumber( DOMDocument*, const std::string& name ) const;
    00499   int addXMLComponentFields( DOMDocument*, DOMNode*, const std::string& msgtype, DataDictionary&, bool );
    00500   void addXMLGroup( DOMDocument*, DOMNode*, const std::string& msgtype, DataDictionary&, bool );
    00501   TYPE::Type XMLTypeToType( const std::string& xmlType ) const;
    00502
    00503   bool m_hasVersion;
    00504   bool m_checkFieldsOutOfOrder;
    00505   bool m_checkFieldsHaveValues;
    00506   bool m_checkUserDefinedFields;
    00507   BeginString m_beginString;
    00508   MsgTypeToField m_messageFields;
    00509   MsgTypeToField m_requiredFields;
    00510   MsgTypes m_messages;
    00511   Fields m_fields;
    00512   OrderedFields m_orderedFields;
    00513   mutable OrderedFieldsArray m_orderedFieldsArray;
    00514   NonBodyFields m_headerFields;
    00515   NonBodyFields m_trailerFields;
    00516   FieldTypes m_fieldTypes;
    00517   FieldToValue m_fieldValues;
    00518   FieldToName m_fieldNames;
    00519   NameToField m_names;
    00520   ValueToName m_valueNames;
    00521   FieldToGroup m_groups;
    00522 };
    00523 }
    00524
    00525 #endif //FIX_DATADICTIONARY_H