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

Message.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_MESSAGE
00023 #define FIX_MESSAGE
00024 
00025 #ifdef _MSC_VER
00026 #pragma warning( disable: 4786 )
00027 #endif
00028 
00029 #include "FieldMap.h"
00030 #include "Fields.h"
00031 #include "Group.h"
00032 #include "SessionID.h"
00033 #include "DataDictionary.h"
00034 #include "CallStack.h"
00035 #include "Values.h"
00036 #include <vector>
00037 #include <memory>
00038 
00039 namespace FIX
00040 {
00041 typedef FieldMap Header;
00042 typedef FieldMap Trailer;
00043 
00044 static int const headerOrder[] =
00045   {
00046     FIELD::BeginString,
00047     FIELD::BodyLength,
00048     FIELD::MsgType
00049   };
00050 
00057 class Message : public FieldMap
00058 {
00059   friend class DataDictionary;
00060   friend class Session;
00061 
00062   enum field_type { header, body, trailer };
00063 
00064 public:
00065   Message();
00066 
00068   Message( const std::string& string, bool validate = true )
00069   throw( InvalidMessage );
00070 
00072   Message( const std::string& string, const FIX::DataDictionary& dataDictionary,
00073            bool validate = true )
00074   throw( InvalidMessage );
00075 
00077   Message( const std::string& string, const FIX::DataDictionary& sessionDataDictionary,
00078            const FIX::DataDictionary& applicationDataDictionary, bool validate = true )
00079   throw( InvalidMessage );
00080 
00081   Message( const Message& copy )
00082   : FieldMap( copy ),
00083     m_header( message_order( message_order::header ) ),
00084     m_trailer( message_order( message_order::trailer ) )
00085   {
00086     m_header = copy.m_header;
00087     m_trailer = copy.m_trailer;
00088     m_validStructure = copy.m_validStructure;
00089     m_field = copy.m_field;
00090   }
00091 
00093   static bool InitializeXML( const std::string& string );
00094 
00095   void addGroup( FIX::Group& group )
00096   { FieldMap::addGroup( group.field(), group ); }
00097 
00098   void replaceGroup( unsigned num, FIX::Group& group )
00099   { FieldMap::replaceGroup( num, group.field(), group ); }
00100 
00101   Group& getGroup( unsigned num, FIX::Group& group ) const throw( FieldNotFound )
00102   { group.clear();
00103     return static_cast < Group& >
00104       ( FieldMap::getGroup( num, group.field(), group ) );
00105   }
00106 
00107   void removeGroup( unsigned num, FIX::Group& group )
00108   { FieldMap::removeGroup( num, group.field() ); }
00109   void removeGroup( FIX::Group& group )
00110   { FieldMap::removeGroup( group.field() ); }
00111 
00112   bool hasGroup( const FIX::Group& group ) const
00113   { return FieldMap::hasGroup( group.field() ); }
00114   bool hasGroup( unsigned num, FIX::Group& group ) const
00115   { return FieldMap::hasGroup( num, group.field() ); }
00116 
00117 protected:
00118   // Constructor for derived classes
00119   Message( const BeginString& beginString, const MsgType& msgType )
00120   : m_header( message_order( message_order::header ) ),
00121   m_trailer( message_order( message_order::trailer ) ),
00122   m_validStructure( true )
00123   {
00124     m_header.setField( beginString );
00125     m_header.setField( msgType );
00126   }
00127 
00128 public:
00130   std::string toString( int beginStringField = FIELD::BeginString,
00131                         int bodyLengthField = FIELD::BodyLength,
00132                         int checkSumField = FIELD::CheckSum ) const;
00134   std::string& toString( std::string&,
00135                          int beginStringField = FIELD::BeginString,
00136                          int bodyLengthField = FIELD::BodyLength, 
00137                          int checkSumField = FIELD::CheckSum ) const;
00139   std::string toXML() const;
00141   std::string& toXML( std::string& ) const;
00142 
00148   void reverseRoute( const Header& );
00149 
00156   void setString( const std::string& string )
00157   { setString(string, true); }
00158   void setString( const std::string& string, bool validate )
00159   { setString(string, validate, 0); }
00160   void setString( const std::string& string,
00161                   bool validate,
00162                   const FIX::DataDictionary* pDataDictionary )
00163   throw( InvalidMessage )
00164   { setString(string, validate, pDataDictionary, pDataDictionary); }
00165 
00166   void setString( const std::string& string,
00167                   bool validate,
00168                   const FIX::DataDictionary* pSessionDataDictionary,
00169                   const FIX::DataDictionary* pApplicationDataDictionary )
00170   throw( InvalidMessage );
00171 
00172   void setGroup( const std::string& msg, const FieldBase& field,
00173                  const std::string& string, std::string::size_type& pos,
00174                  FieldMap& map, const DataDictionary& dataDictionary );
00175 
00181   bool setStringHeader( const std::string& string );
00182 
00184   const Header& getHeader() const { return m_header; }
00186   Header& getHeader() { return m_header; }
00188   const Header& getTrailer() const { return m_trailer; }
00190   Trailer& getTrailer() { return m_trailer; }
00191 
00192   bool hasValidStructure(int& field) const
00193   { field = m_field;
00194     return m_validStructure;
00195   }
00196 
00197   int bodyLength( int beginStringField = FIELD::BeginString, 
00198                   int bodyLengthField = FIELD::BodyLength, 
00199                   int checkSumField = FIELD::CheckSum ) const
00200   { return m_header.calculateLength(beginStringField, bodyLengthField, checkSumField)
00201            + calculateLength(beginStringField, bodyLengthField, checkSumField)
00202            + m_trailer.calculateLength(beginStringField, bodyLengthField, checkSumField);
00203   }
00204 
00205   int checkSum( int checkSumField = FIELD::CheckSum ) const
00206   { return ( m_header.calculateTotal(checkSumField)
00207              + calculateTotal(checkSumField)
00208              + m_trailer.calculateTotal(checkSumField) ) % 256;
00209   }
00210 
00211   bool isAdmin() const
00212   { 
00213     if( m_header.isSetField(FIELD::MsgType) )
00214     {
00215       const MsgType& msgType = FIELD_GET_REF( m_header, MsgType );
00216       return isAdminMsgType( msgType );
00217     }
00218     return false;
00219   }
00220 
00221   bool isApp() const
00222   { 
00223     if( m_header.isSetField(FIELD::MsgType) )
00224     {
00225       const MsgType& msgType = FIELD_GET_REF( m_header, MsgType );
00226       return !isAdminMsgType( msgType );
00227     }
00228     return false;
00229   }
00230 
00231   bool isEmpty()
00232   { return m_header.isEmpty() && FieldMap::isEmpty() && m_trailer.isEmpty(); }
00233 
00234   void clear()
00235   { 
00236     m_field = 0;
00237     m_header.clear();
00238     FieldMap::clear();
00239     m_trailer.clear();
00240   }
00241 
00242   static bool isAdminMsgType( const MsgType& msgType )
00243   { if ( msgType.getValue().length() != 1 ) return false;
00244     return strchr
00245            ( "0A12345",
00246              msgType.getValue().c_str() [ 0 ] ) != 0;
00247   }
00248 
00249   static ApplVerID toApplVerID(const BeginString& value)
00250   { QF_STACK_PUSH(SessionFactory::toApplVerID)
00251 
00252     if( value == BeginString_FIX40 )
00253       return ApplVerID(ApplVerID_FIX40);
00254     if( value == BeginString_FIX41 )
00255       return ApplVerID(ApplVerID_FIX41);
00256     if( value == BeginString_FIX42 )
00257       return ApplVerID(ApplVerID_FIX42);
00258     if( value == BeginString_FIX43 )
00259       return ApplVerID(ApplVerID_FIX43);
00260     if( value == BeginString_FIX44 )
00261       return ApplVerID(ApplVerID_FIX44);
00262     if( value == BeginString_FIX50 )
00263       return ApplVerID(ApplVerID_FIX50);
00264     if( value == "FIX.5.0SP1" )
00265       return ApplVerID(ApplVerID_FIX50SP1);
00266     if( value == "FIX.5.0SP2" )
00267       return ApplVerID(ApplVerID_FIX50SP2);
00268     return ApplVerID(ApplVerID(value));
00269 
00270     QF_STACK_POP
00271   }
00272 
00273   static BeginString toBeginString( const ApplVerID& applVerID )
00274   {
00275     if( applVerID == ApplVerID_FIX40 )
00276       return BeginString(BeginString_FIX40);
00277     else if( applVerID == ApplVerID_FIX41 )
00278       return BeginString(BeginString_FIX41);
00279     else if( applVerID == ApplVerID_FIX42 )
00280       return BeginString(BeginString_FIX42);
00281     else if( applVerID == ApplVerID_FIX43 )
00282       return BeginString(BeginString_FIX43);
00283     else if( applVerID == ApplVerID_FIX44 )
00284       return BeginString(BeginString_FIX44);
00285     else if( applVerID == ApplVerID_FIX50 )
00286       return BeginString(BeginString_FIX50);
00287     else if( applVerID == ApplVerID_FIX50SP1 )
00288       return BeginString(BeginString_FIX50);
00289     else if( applVerID == ApplVerID_FIX50SP2 )
00290       return BeginString(BeginString_FIX50);
00291     else
00292       return BeginString("");
00293   }
00294 
00295   static bool isHeaderField( int field );
00296   static bool isHeaderField( const FieldBase& field,
00297                              const DataDictionary* pD = 0 );
00298 
00299   static bool isTrailerField( int field );
00300   static bool isTrailerField( const FieldBase& field,
00301                               const DataDictionary* pD = 0 );
00302 
00304   SessionID getSessionID( const std::string& qualifier = "" ) const
00305   throw( FieldNotFound );
00307   void setSessionID( const SessionID& sessionID );
00308 
00309 private:
00310   FieldBase extractField
00311   ( const std::string& string, std::string::size_type& pos,
00312     const DataDictionary* pSessionDD = 0, const DataDictionary* pAppDD = 0,
00313     const Group* pGroup = 0)
00314   { QF_STACK_PUSH(extractField)
00315 
00316     std::string::size_type equalSign
00317       = string.find_first_of( '=', pos );
00318     if( equalSign == std::string::npos )
00319       throw InvalidMessage("Equal sign not found in field");
00320 
00321     char* pEnd = 0;
00322     int field = strtol( string.c_str() + pos, &pEnd, 0 );
00323 
00324     std::string::size_type soh =
00325       string.find_first_of( '\001', equalSign + 1 );
00326     if ( soh == std::string::npos )
00327       throw InvalidMessage("SOH not found at end of field");
00328 
00329     if ( (pSessionDD && pSessionDD->isDataField(field)) || (pAppDD && pAppDD->isDataField(field)) )
00330     {
00331       std::string fieldLength;
00332       // Assume length field is 1 less.
00333       int lenField = field - 1;
00334       // Special case for Signature which violates above assumption.
00335       if ( field == 89 ) lenField = 93;
00336 
00337       if ( pGroup && pGroup->isSetField( lenField ) )
00338       {
00339         fieldLength = pGroup->getField( lenField );
00340         soh = equalSign + 1 + atol( fieldLength.c_str() );
00341       }
00342       else if ( isSetField( lenField ) )
00343       {
00344         fieldLength = getField( lenField );
00345         soh = equalSign + 1 + atol( fieldLength.c_str() );
00346       }
00347     }
00348 
00349     pos = soh + 1;
00350     return FieldBase (
00351       field,
00352       string.substr( equalSign + 1, soh - ( equalSign + 1 ) ) );
00353 
00354     QF_STACK_POP
00355   }
00356 
00357   void validate();
00358   std::string toXMLFields(const FieldMap& fields, int space) const;
00359 
00360 protected:
00361   mutable FieldMap m_header;
00362   mutable FieldMap m_trailer;
00363   bool m_validStructure;
00364   int m_field;
00365   static std::auto_ptr<DataDictionary> s_dataDictionary;
00366 };
00369 inline std::ostream& operator <<
00370 ( std::ostream& stream, const Message& message )
00371 {
00372   std::string str;
00373   stream << message.toString( str );
00374   return stream;
00375 }
00376 
00378 inline MsgType identifyType( const std::string& message )
00379 throw( MessageParseError )
00380 {
00381   std::string::size_type pos = message.find( "\00135=" );
00382   if ( pos == std::string::npos ) throw MessageParseError();
00383 
00384   std::string::size_type startValue = pos + 4;
00385   std::string::size_type soh = message.find_first_of( '\001', startValue );
00386   if ( soh == std::string::npos ) throw MessageParseError();
00387 
00388   std::string value = message.substr( startValue, soh - startValue );
00389   return MsgType( value );
00390 }
00391 }
00392 
00393 #endif //FIX_MESSAGE

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