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

Generated on Mon Apr 5 20:59:50 2010 for QuickFIX by doxygen 1.6.1 written by Dimitri van Heesch, © 1997-2001