00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef _MSC_VER
00021 #include "stdafx.h"
00022 #else
00023 #include "config.h"
00024 #endif
00025 #include "CallStack.h"
00026
00027 #include "Message.h"
00028 #include "Utility.h"
00029 #include "Values.h"
00030 #include <iomanip>
00031
00032 namespace FIX
00033 {
00034 std::auto_ptr<DataDictionary> Message::s_dataDictionary;
00035
00036 Message::Message()
00037 : m_header( message_order( message_order::header ) ),
00038 m_trailer( message_order( message_order::trailer ) ),
00039 m_validStructure( true ) {}
00040
00041 Message::Message( const std::string& string, bool validate )
00042 throw( InvalidMessage )
00043 : m_header( message_order( message_order::header ) ),
00044 m_trailer( message_order( message_order::trailer ) ),
00045 m_validStructure( true )
00046 {
00047 setString( string, validate );
00048 }
00049
00050 Message::Message( const std::string& string,
00051 const DataDictionary& dataDictionary,
00052 bool validate )
00053 throw( InvalidMessage )
00054 : m_header( message_order( message_order::header ) ),
00055 m_trailer( message_order( message_order::trailer ) ),
00056 m_validStructure( true )
00057 {
00058 setString( string, validate, &dataDictionary );
00059 }
00060
00061 bool Message::InitializeXML( const std::string& url )
00062 { QF_STACK_PUSH(Message::InitializeXML)
00063
00064 try
00065 {
00066 std::auto_ptr<DataDictionary> p =
00067 std::auto_ptr<DataDictionary>(new DataDictionary(url));
00068 s_dataDictionary = p;
00069 return true;
00070 }
00071 catch( ConfigError& )
00072 { return false; }
00073
00074 QF_STACK_POP
00075 }
00076
00077 void Message::reverseRoute( const Header& header )
00078 { QF_STACK_PUSH(Message::reverseRoute)
00079
00080
00081 BeginString beginString;
00082 SenderCompID senderCompID;
00083 TargetCompID targetCompID;
00084
00085 m_header.removeField( beginString.getField() );
00086 m_header.removeField( senderCompID.getField() );
00087 m_header.removeField( targetCompID.getField() );
00088
00089 if( header.isSetField( beginString ) )
00090 {
00091 header.getField( beginString );
00092 if( beginString.getValue().size() )
00093 m_header.setField( beginString );
00094
00095 OnBehalfOfLocationID onBehalfOfLocationID;
00096 DeliverToLocationID deliverToLocationID;
00097
00098 m_header.removeField( onBehalfOfLocationID.getField() );
00099 m_header.removeField( deliverToLocationID.getField() );
00100
00101 if( beginString >= BeginString_FIX41 )
00102 {
00103 if( header.isSetField( onBehalfOfLocationID ) )
00104 {
00105 header.getField( onBehalfOfLocationID );
00106 if( onBehalfOfLocationID.getValue().size() )
00107 m_header.setField( DeliverToLocationID( onBehalfOfLocationID ) );
00108 }
00109
00110 if( header.isSetField( deliverToLocationID ) )
00111 {
00112 header.getField( deliverToLocationID );
00113 if( deliverToLocationID.getValue().size() )
00114 m_header.setField( OnBehalfOfLocationID( deliverToLocationID ) );
00115 }
00116 }
00117 }
00118
00119 if( header.isSetField( senderCompID ) )
00120 {
00121 header.getField( senderCompID );
00122 if( senderCompID.getValue().size() )
00123 m_header.setField( TargetCompID( senderCompID ) );
00124 }
00125
00126 if( header.isSetField( targetCompID ) )
00127 {
00128 header.getField( targetCompID );
00129 if( targetCompID.getValue().size() )
00130 m_header.setField( SenderCompID( targetCompID ) );
00131 }
00132
00133
00134 OnBehalfOfCompID onBehalfOfCompID;
00135 OnBehalfOfSubID onBehalfOfSubID;
00136 DeliverToCompID deliverToCompID;
00137 DeliverToSubID deliverToSubID;
00138
00139 m_header.removeField( onBehalfOfCompID.getField() );
00140 m_header.removeField( onBehalfOfSubID.getField() );
00141 m_header.removeField( deliverToCompID.getField() );
00142 m_header.removeField( deliverToSubID.getField() );
00143
00144 if( header.isSetField( onBehalfOfCompID ) )
00145 {
00146 header.getField( onBehalfOfCompID );
00147 if( onBehalfOfCompID.getValue().size() )
00148 m_header.setField( DeliverToCompID( onBehalfOfCompID ) );
00149 }
00150
00151 if( header.isSetField( onBehalfOfSubID ) )
00152 {
00153 header.getField( onBehalfOfSubID );
00154 if( onBehalfOfSubID.getValue().size() )
00155 m_header.setField( DeliverToSubID( onBehalfOfSubID ) );
00156 }
00157
00158 if( header.isSetField( deliverToCompID ) )
00159 {
00160 header.getField( deliverToCompID );
00161 if( deliverToCompID.getValue().size() )
00162 m_header.setField( OnBehalfOfCompID( deliverToCompID ) );
00163 }
00164
00165 if( header.isSetField( deliverToSubID ) )
00166 {
00167 header.getField( deliverToSubID );
00168 if( deliverToSubID.getValue().size() )
00169 m_header.setField( OnBehalfOfSubID( deliverToSubID ) );
00170 }
00171
00172 QF_STACK_POP
00173 }
00174
00175 std::string Message::toString( int beginStringField,
00176 int bodyLengthField,
00177 int checkSumField ) const
00178 { QF_STACK_PUSH(Message::toString)
00179
00180 std::string str;
00181 return toString( str, beginStringField, bodyLengthField, checkSumField );
00182
00183 QF_STACK_POP
00184 }
00185
00186 std::string& Message::toString( std::string& str,
00187 int beginStringField,
00188 int bodyLengthField,
00189 int checkSumField ) const
00190 { QF_STACK_PUSH(Message::toString)
00191
00192 int length = bodyLength( beginStringField, bodyLengthField, checkSumField );
00193 m_header.setField( IntField(bodyLengthField, length) );
00194 m_trailer.setField( CheckSumField(checkSumField, checkSum(checkSumField)) );
00195
00196 m_header.calculateString( str, true );
00197 FieldMap::calculateString( str, false );
00198 m_trailer.calculateString( str, false );
00199
00200 return str;
00201
00202 QF_STACK_POP
00203 }
00204
00205 std::string Message::toXML() const
00206 { QF_STACK_PUSH(Message::toXML)
00207
00208 std::string str;
00209 return toXML( str );
00210
00211 QF_STACK_POP
00212 }
00213
00214 std::string& Message::toXML( std::string& str ) const
00215 { QF_STACK_PUSH(Message::toXML)
00216
00217 std::stringstream stream;
00218 stream << "<message>" << std::endl
00219 << std::setw(2) << " " << "<header>" << std::endl
00220 << toXMLFields(getHeader(), 4)
00221 << std::setw(2) << " " << "</header>" << std::endl
00222 << std::setw(2) << " " << "<body>" << std::endl
00223 << toXMLFields(*this, 4)
00224 << std::setw(2) << " " << "</body>" << std::endl
00225 << std::setw(2) << " " << "<trailer>" << std::endl
00226 << toXMLFields(getTrailer(), 4)
00227 << std::setw(2) << " " << "</trailer>" << std::endl
00228 << "</message>";
00229
00230 return str = stream.str();
00231
00232 QF_STACK_POP
00233 }
00234
00235 std::string Message::toXMLFields(const FieldMap& fields, int space) const
00236 { QF_STACK_PUSH(Message::toXMLFields)
00237
00238 std::stringstream stream;
00239 FieldMap::iterator i;
00240 std::string name;
00241 for(i = fields.begin(); i != fields.end(); ++i)
00242 {
00243 int field = i->first;
00244 std::string value = i->second.getString();
00245
00246 stream << std::setw(space) << " " << "<field ";
00247 if(s_dataDictionary.get() && s_dataDictionary->getFieldName(field, name))
00248 {
00249 stream << "name=\"" << name << "\" ";
00250 }
00251 stream << "number=\"" << field << "\"";
00252 if(s_dataDictionary.get()
00253 && s_dataDictionary->getValueName(field, value, name))
00254 {
00255 stream << " enum=\"" << name << "\"";
00256 }
00257 stream << ">";
00258 stream << "<![CDATA[" << value << "]]>";
00259 stream << "</field>" << std::endl;
00260 }
00261
00262 FieldMap::g_iterator j;
00263 for(j = fields.g_begin(); j != fields.g_end(); ++j)
00264 {
00265 std::vector<FieldMap*>::const_iterator k;
00266 for(k = j->second.begin(); k != j->second.end(); ++k)
00267 {
00268 stream << std::setw(space) << " " << "<group>" << std::endl
00269 << toXMLFields(*(*k), space+2)
00270 << std::setw(space) << " " << "</group>" << std::endl;
00271 }
00272 }
00273
00274 return stream.str();
00275
00276 QF_STACK_POP
00277 }
00278
00279 void Message::setString( const std::string& string,
00280 bool doValidation,
00281 const DataDictionary* pDataDictionary )
00282 throw( InvalidMessage )
00283 { QF_STACK_PUSH(Message::setString)
00284
00285 clear();
00286
00287 std::string::size_type pos = 0;
00288 int count = 0;
00289 std::string msg;
00290
00291 static FIELD::Field const headerOrder[] =
00292 {
00293 FIELD::BeginString,
00294 FIELD::BodyLength,
00295 FIELD::MsgType
00296 };
00297
00298 field_type type = header;
00299
00300 while ( pos < string.size() )
00301 {
00302 FieldBase field = extractField( string, pos, pDataDictionary );
00303 if ( count < 3 && headerOrder[ count++ ] != field.getField() )
00304 if ( doValidation ) throw InvalidMessage("Header fields out of order");
00305
00306 if ( isHeaderField( field, pDataDictionary ) )
00307 {
00308 if ( type != header )
00309 {
00310 if(m_field == 0) m_field = field.getField();
00311 m_validStructure = false;
00312 }
00313
00314 if ( field.getField() == FIELD::MsgType )
00315 msg = field.getString();
00316
00317 m_header.setField( field, false );
00318
00319 if ( pDataDictionary )
00320 setGroup( "_header_", field, string, pos, getHeader(), *pDataDictionary );
00321 }
00322 else if ( isTrailerField( field, pDataDictionary ) )
00323 {
00324 type = trailer;
00325 m_trailer.setField( field, false );
00326
00327 if ( pDataDictionary )
00328 setGroup( "_trailer_", field, string, pos, getTrailer(), *pDataDictionary );
00329 }
00330 else
00331 {
00332 if ( type == trailer )
00333 {
00334 if(m_field == 0) m_field = field.getField();
00335 m_validStructure = false;
00336 }
00337
00338 type = body;
00339 setField( field, false );
00340
00341 if ( pDataDictionary )
00342 setGroup( msg, field, string, pos, *this, *pDataDictionary );
00343 }
00344 }
00345
00346 if ( doValidation )
00347 validate();
00348
00349 QF_STACK_POP
00350 }
00351
00352 void Message::setGroup( const std::string& msg, const FieldBase& field,
00353 const std::string& string,
00354 std::string::size_type& pos, FieldMap& map,
00355 const DataDictionary& dataDictionary )
00356 { QF_STACK_PUSH(Message::setGroup)
00357
00358 int group = field.getField();
00359 int delim;
00360 const DataDictionary* pDD = 0;
00361 if ( !dataDictionary.getGroup( msg, group, delim, pDD ) ) return ;
00362 Group* pGroup = 0;
00363
00364 while ( pos < string.size() )
00365 {
00366 std::string::size_type oldPos = pos;
00367 FieldBase field = extractField( string, pos, &dataDictionary, pGroup );
00368 if ( (field.getField() == delim)
00369 || (pGroup == 0 && pDD->isField(field.getField())) )
00370 {
00371 if ( pGroup )
00372 {
00373 map.addGroup( group, *pGroup, false );
00374 delete pGroup; pGroup = 0;
00375 }
00376 pGroup = new Group( field.getField(), delim, pDD->getOrderedFields() );
00377 }
00378 else if ( !pDD->isField( field.getField() ) )
00379 {
00380 if ( pGroup )
00381 {
00382 map.addGroup( group, *pGroup, false );
00383 delete pGroup; pGroup = 0;
00384 }
00385 pos = oldPos;
00386 return ;
00387 }
00388
00389 if ( !pGroup ) return ;
00390 pGroup->setField( field, false );
00391 setGroup( msg, field, string, pos, *pGroup, *pDD );
00392 }
00393
00394 QF_STACK_POP
00395 }
00396
00397 bool Message::setStringHeader( const std::string& string )
00398 { QF_STACK_PUSH(Message::setStringHeader)
00399
00400 clear();
00401
00402 std::string::size_type pos = 0;
00403 int count = 0;
00404
00405 while ( pos < string.size() )
00406 {
00407 FieldBase field = extractField( string, pos );
00408 if ( count < 3 && headerOrder[ count++ ] != field.getField() )
00409 return false;
00410
00411 if ( isHeaderField( field ) )
00412 m_header.setField( field, false );
00413 else break;
00414 }
00415 return true;
00416
00417 QF_STACK_POP
00418 }
00419
00420 bool Message::isHeaderField( int field )
00421 { QF_STACK_PUSH(Message::isHeaderField)
00422
00423 switch ( field )
00424 {
00425 case FIELD::BeginString:
00426 case FIELD::BodyLength:
00427 case FIELD::MsgType:
00428 case FIELD::SenderCompID:
00429 case FIELD::TargetCompID:
00430 case FIELD::OnBehalfOfCompID:
00431 case FIELD::DeliverToCompID:
00432 case FIELD::SecureDataLen:
00433 case FIELD::MsgSeqNum:
00434 case FIELD::SenderSubID:
00435 case FIELD::SenderLocationID:
00436 case FIELD::TargetSubID:
00437 case FIELD::TargetLocationID:
00438 case FIELD::OnBehalfOfSubID:
00439 case FIELD::OnBehalfOfLocationID:
00440 case FIELD::DeliverToSubID:
00441 case FIELD::DeliverToLocationID:
00442 case FIELD::PossDupFlag:
00443 case FIELD::PossResend:
00444 case FIELD::SendingTime:
00445 case FIELD::OrigSendingTime:
00446 case FIELD::XmlDataLen:
00447 case FIELD::XmlData:
00448 case FIELD::MessageEncoding:
00449 case FIELD::LastMsgSeqNumProcessed:
00450 case FIELD::OnBehalfOfSendingTime:
00451 return true;
00452 default:
00453 return false;
00454 };
00455
00456 QF_STACK_POP
00457 }
00458
00459 bool Message::isHeaderField( const FieldBase& field,
00460 const DataDictionary* pD )
00461 { QF_STACK_PUSH(Message::isHeaderField)
00462
00463 if ( isHeaderField( field.getField() ) ) return true;
00464 if ( pD ) return pD->isHeaderField( field.getField() );
00465 return false;
00466
00467 QF_STACK_POP
00468 }
00469
00470 bool Message::isTrailerField( int field )
00471 { QF_STACK_PUSH(Message::isTrailerField)
00472
00473 switch ( field )
00474 {
00475 case FIELD::SignatureLength:
00476 case FIELD::Signature:
00477 case FIELD::CheckSum:
00478 return true;
00479 default:
00480 return false;
00481 };
00482
00483 QF_STACK_POP
00484 }
00485
00486 bool Message::isTrailerField( const FieldBase& field,
00487 const DataDictionary* pD )
00488 { QF_STACK_PUSH(Message::isTrailerField)
00489
00490 if ( isTrailerField( field.getField() ) ) return true;
00491 if ( pD ) return pD->isTrailerField( field.getField() );
00492 return false;
00493
00494 QF_STACK_POP
00495 }
00496
00497 SessionID Message::getSessionID( const std::string& qualifier )
00498 throw( FieldNotFound )
00499 { QF_STACK_PUSH(Message::getSessionID)
00500
00501 BeginString beginString;
00502 SenderCompID senderCompID;
00503 TargetCompID targetCompID;
00504
00505 getHeader().getField( beginString );
00506 getHeader().getField( senderCompID );
00507 getHeader().getField( targetCompID );
00508
00509 return SessionID( beginString, senderCompID, targetCompID, qualifier );
00510
00511 QF_STACK_POP
00512 }
00513
00514 void Message::setSessionID( const SessionID& sessionID )
00515 { QF_STACK_PUSH(Message::setSessionID)
00516
00517 getHeader().setField( sessionID.getBeginString() );
00518 getHeader().setField( sessionID.getSenderCompID() );
00519 getHeader().setField( sessionID.getTargetCompID() );
00520
00521 QF_STACK_POP
00522 }
00523
00524 void Message::validate()
00525 { QF_STACK_PUSH(Message::validate)
00526
00527 try
00528 {
00529 BodyLength aBodyLength;
00530 m_header.getField( aBodyLength );
00531 if ( aBodyLength != bodyLength() )
00532 {
00533 std::stringstream text;
00534 text << "Expected BodyLength=" << bodyLength()
00535 << ", Recieved BodyLength=" << (int)aBodyLength;
00536 throw InvalidMessage(text.str());
00537 }
00538
00539 CheckSum aCheckSum;
00540 m_trailer.getField( aCheckSum );
00541 if ( aCheckSum != checkSum() )
00542 {
00543 std::stringstream text;
00544 text << "Expected CheckSum=" << checkSum()
00545 << ", Recieved CheckSum=" << (int)aCheckSum;
00546 throw InvalidMessage(text.str());
00547 }
00548 }
00549 catch ( FieldNotFound& )
00550 {
00551 throw InvalidMessage("BodyLength or CheckSum missing");
00552 }
00553
00554 QF_STACK_POP
00555 }
00556 }