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 == ApplVerId_FIX40 )
00253       return ApplVerID(ApplVerID_FIX40);
00254     if( value == ApplVerId_FIX41 )
00255       return ApplVerID(ApplVerID_FIX41);
00256     if( value == ApplVerId_FIX42 )
00257       return ApplVerID(ApplVerID_FIX42);
00258     if( value == ApplVerId_FIX43 )
00259       return ApplVerID(ApplVerID_FIX43);
00260     if( value == ApplVerId_FIX44 )
00261       return ApplVerID(ApplVerID_FIX44);
00262     if( value == ApplVerId_FIX50 )
00263       return ApplVerID(ApplVerID_FIX50);
00264     return ApplVerID(ApplVerID(value));
00265 
00266     QF_STACK_POP
00267   }
00268 
00269   static BeginString toBeginString( const ApplVerID& applVerID )
00270   {
00271     if( applVerID == ApplVerID_FIX40 )
00272       return BeginString(BeginString_FIX40);
00273     else if( applVerID == ApplVerID_FIX41 )
00274       return BeginString(BeginString_FIX41);
00275     else if( applVerID == ApplVerID_FIX42 )
00276       return BeginString(BeginString_FIX42);
00277     else if( applVerID == ApplVerID_FIX43 )
00278       return BeginString(BeginString_FIX43);
00279     else if( applVerID == ApplVerID_FIX44 )
00280       return BeginString(BeginString_FIX44);
00281     else if( applVerID == ApplVerID_FIX50 )
00282       return BeginString(ApplVerId_FIX50);
00283     else
00284       return BeginString("");
00285   }
00286 
00287   static bool isHeaderField( int field );
00288   static bool isHeaderField( const FieldBase& field,
00289                              const DataDictionary* pD = 0 );
00290 
00291   static bool isTrailerField( int field );
00292   static bool isTrailerField( const FieldBase& field,
00293                               const DataDictionary* pD = 0 );
00294 
00296   SessionID getSessionID( const std::string& qualifier = "" ) const
00297   throw( FieldNotFound );
00299   void setSessionID( const SessionID& sessionID );
00300 
00301 private:
00302   FieldBase extractField
00303   ( const std::string& string, std::string::size_type& pos,
00304     const DataDictionary* pSessionDD = 0, const DataDictionary* pAppDD = 0,
00305     const Group* pGroup = 0)
00306   { QF_STACK_PUSH(extractField)
00307 
00308     std::string::size_type equalSign
00309       = string.find_first_of( '=', pos );
00310     if( equalSign == std::string::npos )
00311       throw InvalidMessage("Equal sign not found in field");
00312 
00313     char* pEnd = 0;
00314     int field = strtol( string.c_str() + pos, &pEnd, 0 );
00315 
00316     std::string::size_type soh =
00317       string.find_first_of( '\001', equalSign + 1 );
00318     if ( soh == std::string::npos )
00319       throw InvalidMessage("SOH not found at end of field");
00320 
00321     if ( (pSessionDD && pSessionDD->isDataField(field)) || (pAppDD && pAppDD->isDataField(field)) )
00322     {
00323       std::string fieldLength;
00324       // Assume length field is 1 less.
00325       int lenField = field - 1;
00326       // Special case for Signature which violates above assumption.
00327       if ( field == 89 ) lenField = 93;
00328 
00329       if ( pGroup && pGroup->isSetField( lenField ) )
00330       {
00331         fieldLength = pGroup->getField( lenField );
00332         soh = equalSign + 1 + atol( fieldLength.c_str() );
00333       }
00334       else if ( isSetField( lenField ) )
00335       {
00336         fieldLength = getField( lenField );
00337         soh = equalSign + 1 + atol( fieldLength.c_str() );
00338       }
00339     }
00340 
00341     pos = soh + 1;
00342     return FieldBase (
00343       field,
00344       string.substr( equalSign + 1, soh - ( equalSign + 1 ) ) );
00345 
00346     QF_STACK_POP
00347   }
00348 
00349   void validate();
00350   std::string toXMLFields(const FieldMap& fields, int space) const;
00351 
00352 protected:
00353   mutable FieldMap m_header;
00354   mutable FieldMap m_trailer;
00355   bool m_validStructure;
00356   int m_field;
00357   static std::auto_ptr<DataDictionary> s_dataDictionary;
00358 };
00361 inline std::ostream& operator <<
00362 ( std::ostream& stream, const Message& message )
00363 {
00364   std::string str;
00365   stream << message.toString( str );
00366   return stream;
00367 }
00368 
00370 inline MsgType identifyType( const std::string& message )
00371 throw( MessageParseError )
00372 {
00373   std::string::size_type pos = message.find( "\00135=" );
00374   if ( pos == std::string::npos ) throw MessageParseError();
00375 
00376   std::string::size_type startValue = pos + 4;
00377   std::string::size_type soh = message.find_first_of( '\001', startValue );
00378   if ( soh == std::string::npos ) throw MessageParseError();
00379 
00380   std::string value = message.substr( startValue, soh - startValue );
00381   return MsgType( value );
00382 }
00383 }
00384 
00385 #endif //FIX_MESSAGE

Generated on Mon Mar 1 13:41:38 2010 for QuickFIX by doxygen 1.5.8 written by Dimitri van Heesch, © 1997-2001