DataDictionary.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. /* -*- C++ -*- */
  2. /****************************************************************************
  3. ** Copyright (c) 2001-2014
  4. **
  5. ** This file is part of the QuickFIX FIX Engine
  6. **
  7. ** This file may be distributed under the terms of the quickfixengine.org
  8. ** license as defined by quickfixengine.org and appearing in the file
  9. ** LICENSE included in the packaging of this file.
  10. **
  11. ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
  12. ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  13. **
  14. ** See http://www.quickfixengine.org/LICENSE for licensing information.
  15. **
  16. ** Contact ask@quickfixengine.org if any conditions of this licensing are
  17. ** not clear to you.
  18. **
  19. ****************************************************************************/
  20. #ifndef FIX_DATADICTIONARY_H
  21. #define FIX_DATADICTIONARY_H
  22. #ifdef _MSC_VER
  23. #pragma warning( disable : 4503 4355 4786 4290 )
  24. #endif
  25. #include "Fields.h"
  26. #include "FieldMap.h"
  27. #include "DOMDocument.h"
  28. #include "Exceptions.h"
  29. #include <set>
  30. #include <map>
  31. #include <string.h>
  32. namespace FIX
  33. {
  34. class FieldMap;
  35. class Message;
  36. /**
  37. * Represents a data dictionary for a version of %FIX.
  38. *
  39. * Generally loaded from an XML document. The DataDictionary is also
  40. * responsible for validation beyond the basic structure of a message.
  41. */
  42. class DataDictionary
  43. {
  44. typedef std::set < int > MsgFields;
  45. typedef std::map < std::string, MsgFields > MsgTypeToField;
  46. typedef std::set < std::string > MsgTypes;
  47. typedef std::set < int > Fields;
  48. typedef std::map < int, bool > NonBodyFields;
  49. typedef std::vector< int > OrderedFields;
  50. typedef message_order OrderedFieldsArray;
  51. typedef std::map < int, TYPE::Type > FieldTypes;
  52. typedef std::set < std::string > Values;
  53. typedef std::map < int, Values > FieldToValue;
  54. typedef std::map < int, std::string > FieldToName;
  55. typedef std::map < std::string, int > NameToField;
  56. typedef std::map < std::pair < int, std::string > , std::string > ValueToName;
  57. // while FieldToGroup structure seems to be overcomplicated
  58. // in reality it yields a lot of performance because:
  59. // 1) avoids memory copying;
  60. // 2) first lookup is done by comparing integers and not string objects
  61. // TODO: use hash_map with good hashing algorithm
  62. typedef std::map < std::string, std::pair < int, DataDictionary* > > FieldPresenceMap;
  63. typedef std::map < int, FieldPresenceMap > FieldToGroup;
  64. public:
  65. DataDictionary();
  66. DataDictionary( const DataDictionary& copy );
  67. DataDictionary( std::istream& stream ) throw( ConfigError );
  68. DataDictionary( const std::string& url ) throw( ConfigError );
  69. virtual ~DataDictionary();
  70. void readFromURL( const std::string& url ) throw( ConfigError );
  71. void readFromDocument( DOMDocumentPtr pDoc ) throw( ConfigError );
  72. void readFromStream( std::istream& stream ) throw( ConfigError );
  73. message_order const& getOrderedFields() const;
  74. // storage functions
  75. void setVersion( const std::string& beginString )
  76. {
  77. m_beginString = beginString;
  78. m_hasVersion = true;
  79. }
  80. std::string getVersion() const
  81. {
  82. return m_beginString.getString();
  83. }
  84. void addField( int field )
  85. {
  86. m_fields.insert( field );
  87. m_orderedFields.push_back( field );
  88. }
  89. void addFieldName( int field, const std::string& name )
  90. {
  91. if( m_names.insert( std::make_pair(name, field) ).second == false )
  92. throw ConfigError( "Field named " + name + " defined multiple times" );
  93. m_fieldNames[field] = name;
  94. }
  95. bool getFieldName( int field, std::string& name ) const
  96. {
  97. FieldToName::const_iterator i = m_fieldNames.find( field );
  98. if(i == m_fieldNames.end()) return false;
  99. name = i->second;
  100. return true;
  101. }
  102. bool getFieldTag( const std::string& name, int& field ) const
  103. {
  104. NameToField::const_iterator i = m_names.find( name );
  105. if(i == m_names.end()) return false;
  106. field = i->second;
  107. return true;
  108. }
  109. void addValueName( int field, const std::string& value, const std::string& name )
  110. {
  111. m_valueNames[std::make_pair(field, value)] = name;
  112. }
  113. bool getValueName( int field, const std::string& value, std::string& name ) const
  114. {
  115. ValueToName::const_iterator i = m_valueNames.find( std::make_pair(field, value) );
  116. if(i == m_valueNames.end()) return false;
  117. name = i->second;
  118. return true;
  119. }
  120. bool isField( int field ) const
  121. {
  122. return m_fields.find( field ) != m_fields.end();
  123. }
  124. void addMsgType( const std::string& msgType )
  125. {
  126. m_messages.insert( msgType );
  127. }
  128. bool isMsgType( const std::string& msgType ) const
  129. {
  130. return m_messages.find( msgType ) != m_messages.end();
  131. }
  132. void addMsgField( const std::string& msgType, int field )
  133. {
  134. m_messageFields[ msgType ].insert( field );
  135. }
  136. bool isMsgField( const std::string& msgType, int field ) const
  137. {
  138. MsgTypeToField::const_iterator i = m_messageFields.find( msgType );
  139. if ( i == m_messageFields.end() ) return false;
  140. return i->second.find( field ) != i->second.end();
  141. }
  142. void addHeaderField( int field, bool required )
  143. {
  144. m_headerFields[ field ] = required;
  145. }
  146. bool isHeaderField( int field ) const
  147. {
  148. return m_headerFields.find( field ) != m_headerFields.end();
  149. }
  150. void addTrailerField( int field, bool required )
  151. {
  152. m_trailerFields[ field ] = required;
  153. }
  154. bool isTrailerField( int field ) const
  155. {
  156. return m_trailerFields.find( field ) != m_trailerFields.end();
  157. }
  158. void addFieldType( int field, FIX::TYPE::Type type )
  159. {
  160. m_fieldTypes[ field ] = type;
  161. if( type == FIX::TYPE::Data )
  162. m_dataFields.insert( field );
  163. }
  164. bool getFieldType( int field, FIX::TYPE::Type& type ) const
  165. {
  166. FieldTypes::const_iterator i = m_fieldTypes.find( field );
  167. if ( i == m_fieldTypes.end() ) return false;
  168. type = i->second;
  169. return true;
  170. }
  171. void addRequiredField( const std::string& msgType, int field )
  172. {
  173. m_requiredFields[ msgType ].insert( field );
  174. }
  175. bool isRequiredField( const std::string& msgType, int field ) const
  176. {
  177. MsgTypeToField::const_iterator i = m_requiredFields.find( msgType );
  178. if ( i == m_requiredFields.end() ) return false;
  179. return i->second.find( field ) != i->second.end();
  180. }
  181. void addFieldValue( int field, const std::string& value )
  182. {
  183. m_fieldValues[ field ].insert( value );
  184. }
  185. bool hasFieldValue( int field ) const
  186. {
  187. FieldToValue::const_iterator i = m_fieldValues.find( field );
  188. return i != m_fieldValues.end();
  189. }
  190. bool isFieldValue( int field, const std::string& value ) const
  191. {
  192. FieldToValue::const_iterator i = m_fieldValues.find( field );
  193. if ( i == m_fieldValues.end() )
  194. return false;
  195. if( !isMultipleValueField( field ) )
  196. return i->second.find( value ) != i->second.end();
  197. // MultipleValue
  198. std::string::size_type startPos = 0;
  199. std::string::size_type endPos = 0;
  200. do
  201. {
  202. endPos = value.find_first_of(' ', startPos);
  203. std::string singleValue =
  204. value.substr( startPos, endPos - startPos );
  205. if( i->second.find( singleValue ) == i->second.end() )
  206. return false;
  207. startPos = endPos + 1;
  208. } while( endPos != std::string::npos );
  209. return true;
  210. }
  211. void addGroup( const std::string& msg, int field, int delim,
  212. const DataDictionary& dataDictionary )
  213. {
  214. DataDictionary * pDD = new DataDictionary( dataDictionary );
  215. pDD->setVersion( getVersion() );
  216. FieldPresenceMap& presenceMap = m_groups[ field ];
  217. presenceMap[ msg ] = std::make_pair( delim, pDD );
  218. }
  219. bool isGroup( const std::string& msg, int field ) const
  220. {
  221. FieldToGroup::const_iterator i = m_groups.find( field );
  222. if ( i == m_groups.end() ) return false;
  223. const FieldPresenceMap& presenceMap = i->second;
  224. FieldPresenceMap::const_iterator iter = presenceMap.find( msg );
  225. return ( iter != presenceMap.end() );
  226. }
  227. bool getGroup( const std::string& msg, int field, int& delim,
  228. const DataDictionary*& pDataDictionary ) const
  229. {
  230. FieldToGroup::const_iterator i = m_groups.find( field );
  231. if ( i == m_groups.end() ) return false;
  232. const FieldPresenceMap& presenceMap = i->second;
  233. FieldPresenceMap::const_iterator iter = presenceMap.find( msg );
  234. if( iter == presenceMap.end() ) return false;
  235. std::pair < int, DataDictionary* > pair = iter->second;
  236. delim = pair.first;
  237. pDataDictionary = pair.second;
  238. return true;
  239. }
  240. bool isDataField( int field ) const
  241. {
  242. MsgFields::const_iterator iter = m_dataFields.find( field );
  243. return iter != m_dataFields.end();
  244. }
  245. bool isMultipleValueField( int field ) const
  246. {
  247. FieldTypes::const_iterator i = m_fieldTypes.find( field );
  248. return i != m_fieldTypes.end()
  249. && (i->second == TYPE::MultipleValueString
  250. || i->second == TYPE::MultipleCharValue
  251. || i->second == TYPE::MultipleStringValue );
  252. }
  253. void checkFieldsOutOfOrder( bool value )
  254. { m_checkFieldsOutOfOrder = value; }
  255. void checkFieldsHaveValues( bool value )
  256. { m_checkFieldsHaveValues = value; }
  257. void checkUserDefinedFields( bool value )
  258. { m_checkUserDefinedFields = value; }
  259. /// Validate a message.
  260. static void validate( const Message& message,
  261. const DataDictionary* const pSessionDD,
  262. const DataDictionary* const pAppID ) throw( FIX::Exception );
  263. void validate( const Message& message ) const throw ( FIX::Exception )
  264. { validate( message, false ); }
  265. void validate( const Message& message, bool bodyOnly ) const throw( FIX::Exception )
  266. { validate( message, bodyOnly ? (DataDictionary*)0 : this, this ); }
  267. DataDictionary& operator=( const DataDictionary& rhs );
  268. private:
  269. /// Iterate through fields while applying checks.
  270. void iterate( const FieldMap& map, const MsgType& msgType ) const;
  271. /// Check if message type is defined in spec.
  272. void checkMsgType( const MsgType& msgType ) const
  273. {
  274. if ( !isMsgType( msgType.getValue() ) )
  275. throw InvalidMessageType();
  276. }
  277. /// If we need to check for the tag in the dictionary
  278. bool shouldCheckTag( const FieldBase& field ) const
  279. {
  280. if( !m_checkUserDefinedFields && field.getField() >= FIELD::UserMin )
  281. return false;
  282. else
  283. return true;
  284. }
  285. /// Check if field tag number is defined in spec.
  286. void checkValidTagNumber( const FieldBase& field ) const
  287. throw( InvalidTagNumber )
  288. {
  289. if( m_fields.find( field.getField() ) == m_fields.end() )
  290. throw InvalidTagNumber( field.getField() );
  291. }
  292. void checkValidFormat( const FieldBase& field ) const
  293. throw( IncorrectDataFormat )
  294. {
  295. try
  296. {
  297. TYPE::Type type = TYPE::Unknown;
  298. getFieldType( field.getField(), type );
  299. switch ( type )
  300. {
  301. case TYPE::String:
  302. STRING_CONVERTOR::convert( field.getString() ); break;
  303. case TYPE::Char:
  304. CHAR_CONVERTOR::convert( field.getString() ); break;
  305. case TYPE::Price:
  306. PRICE_CONVERTOR::convert( field.getString() ); break;
  307. case TYPE::Int:
  308. INT_CONVERTOR::convert( field.getString() ); break;
  309. case TYPE::Amt:
  310. AMT_CONVERTOR::convert( field.getString() ); break;
  311. case TYPE::Qty:
  312. QTY_CONVERTOR::convert( field.getString() ); break;
  313. case TYPE::Currency:
  314. CURRENCY_CONVERTOR::convert( field.getString() ); break;
  315. case TYPE::MultipleValueString:
  316. MULTIPLEVALUESTRING_CONVERTOR::convert( field.getString() ); break;
  317. case TYPE::MultipleStringValue:
  318. MULTIPLESTRINGVALUE_CONVERTOR::convert( field.getString() ); break;
  319. case TYPE::MultipleCharValue:
  320. MULTIPLECHARVALUE_CONVERTOR::convert( field.getString() ); break;
  321. case TYPE::Exchange:
  322. EXCHANGE_CONVERTOR::convert( field.getString() ); break;
  323. case TYPE::UtcTimeStamp:
  324. UTCTIMESTAMP_CONVERTOR::convert( field.getString() ); break;
  325. case TYPE::Boolean:
  326. BOOLEAN_CONVERTOR::convert( field.getString() ); break;
  327. case TYPE::LocalMktDate:
  328. LOCALMKTDATE_CONVERTOR::convert( field.getString() ); break;
  329. case TYPE::Data:
  330. DATA_CONVERTOR::convert( field.getString() ); break;
  331. case TYPE::Float:
  332. FLOAT_CONVERTOR::convert( field.getString() ); break;
  333. case TYPE::PriceOffset:
  334. PRICEOFFSET_CONVERTOR::convert( field.getString() ); break;
  335. case TYPE::MonthYear:
  336. MONTHYEAR_CONVERTOR::convert( field.getString() ); break;
  337. case TYPE::DayOfMonth:
  338. DAYOFMONTH_CONVERTOR::convert( field.getString() ); break;
  339. case TYPE::UtcDate:
  340. UTCDATE_CONVERTOR::convert( field.getString() ); break;
  341. case TYPE::UtcTimeOnly:
  342. UTCTIMEONLY_CONVERTOR::convert( field.getString() ); break;
  343. case TYPE::NumInGroup:
  344. NUMINGROUP_CONVERTOR::convert( field.getString() ); break;
  345. case TYPE::Percentage:
  346. PERCENTAGE_CONVERTOR::convert( field.getString() ); break;
  347. case TYPE::SeqNum:
  348. SEQNUM_CONVERTOR::convert( field.getString() ); break;
  349. case TYPE::Length:
  350. LENGTH_CONVERTOR::convert( field.getString() ); break;
  351. case TYPE::Country:
  352. COUNTRY_CONVERTOR::convert( field.getString() ); break;
  353. case TYPE::TzTimeOnly:
  354. TZTIMEONLY_CONVERTOR::convert( field.getString() ); break;
  355. case TYPE::TzTimeStamp:
  356. TZTIMESTAMP_CONVERTOR::convert( field.getString() ); break;
  357. case TYPE::XmlData:
  358. XMLDATA_CONVERTOR::convert( field.getString() ); break;
  359. case TYPE::Language:
  360. LANGUAGE_CONVERTOR::convert( field.getString() ); break;
  361. case TYPE::Unknown: break;
  362. }
  363. }
  364. catch ( FieldConvertError& )
  365. { throw IncorrectDataFormat( field.getField(), field.getString() ); }
  366. }
  367. void checkValue( const FieldBase& field ) const
  368. throw( IncorrectTagValue )
  369. {
  370. if ( !hasFieldValue( field.getField() ) ) return ;
  371. const std::string& value = field.getString();
  372. if ( !isFieldValue( field.getField(), value ) )
  373. throw IncorrectTagValue( field.getField() );
  374. }
  375. /// Check if a field has a value.
  376. void checkHasValue( const FieldBase& field ) const
  377. throw( NoTagValue )
  378. {
  379. if ( m_checkFieldsHaveValues && !field.getString().length() )
  380. throw NoTagValue( field.getField() );
  381. }
  382. /// Check if a field is in this message type.
  383. void checkIsInMessage
  384. ( const FieldBase& field, const MsgType& msgType ) const
  385. throw( TagNotDefinedForMessage )
  386. {
  387. if ( !isMsgField( msgType, field.getField() ) )
  388. throw TagNotDefinedForMessage( field.getField() );
  389. }
  390. /// Check if group count matches number of groups in
  391. void checkGroupCount
  392. ( const FieldBase& field, const FieldMap& fieldMap, const MsgType& msgType ) const
  393. throw( RepeatingGroupCountMismatch )
  394. {
  395. int fieldNum = field.getField();
  396. if( isGroup(msgType, fieldNum) )
  397. {
  398. if( fieldMap.groupCount(fieldNum)
  399. != IntConvertor::convert(field.getString()) )
  400. throw RepeatingGroupCountMismatch(fieldNum);
  401. }
  402. }
  403. /// Check if a message has all required fields.
  404. void checkHasRequired
  405. ( const FieldMap& header, const FieldMap& body, const FieldMap& trailer,
  406. const MsgType& msgType ) const
  407. throw( RequiredTagMissing )
  408. {
  409. NonBodyFields::const_iterator iNBF;
  410. for( iNBF = m_headerFields.begin(); iNBF != m_headerFields.end(); ++iNBF )
  411. {
  412. if( iNBF->second == true && !header.isSetField(iNBF->first) )
  413. throw RequiredTagMissing( iNBF->first );
  414. }
  415. for( iNBF = m_trailerFields.begin(); iNBF != m_trailerFields.end(); ++iNBF )
  416. {
  417. if( iNBF->second == true && !trailer.isSetField(iNBF->first) )
  418. throw RequiredTagMissing( iNBF->first );
  419. }
  420. MsgTypeToField::const_iterator iM
  421. = m_requiredFields.find( msgType.getString() );
  422. if ( iM == m_requiredFields.end() ) return ;
  423. const MsgFields& fields = iM->second;
  424. MsgFields::const_iterator iF;
  425. for( iF = fields.begin(); iF != fields.end(); ++iF )
  426. {
  427. if( !body.isSetField(*iF) )
  428. throw RequiredTagMissing( *iF );
  429. }
  430. FieldMap::g_iterator groups;
  431. for( groups = body.g_begin(); groups != body.g_end(); ++groups )
  432. {
  433. int delim;
  434. const DataDictionary* DD = 0;
  435. int field = groups->first;
  436. if( getGroup( msgType.getValue(), field, delim, DD ) )
  437. {
  438. std::vector<FieldMap*>::const_iterator group;
  439. for( group = groups->second.begin(); group != groups->second.end(); ++group )
  440. DD->checkHasRequired( **group, **group, **group, msgType );
  441. }
  442. }
  443. }
  444. /// Read XML file using MSXML.
  445. void readMSXMLDOM( const std::string& );
  446. void readMSXML( const std::string& );
  447. /// Read XML file using libXML.
  448. void readLibXml( const std::string& );
  449. int lookupXMLFieldNumber( DOMDocument*, DOMNode* ) const;
  450. int lookupXMLFieldNumber( DOMDocument*, const std::string& name ) const;
  451. int addXMLComponentFields( DOMDocument*, DOMNode*, const std::string& msgtype, DataDictionary&, bool );
  452. void addXMLGroup( DOMDocument*, DOMNode*, const std::string& msgtype, DataDictionary&, bool );
  453. TYPE::Type XMLTypeToType( const std::string& xmlType ) const;
  454. bool m_hasVersion;
  455. bool m_checkFieldsOutOfOrder;
  456. bool m_checkFieldsHaveValues;
  457. bool m_checkUserDefinedFields;
  458. BeginString m_beginString;
  459. MsgTypeToField m_messageFields;
  460. MsgTypeToField m_requiredFields;
  461. MsgTypes m_messages;
  462. Fields m_fields;
  463. OrderedFields m_orderedFields;
  464. mutable OrderedFieldsArray m_orderedFieldsArray;
  465. NonBodyFields m_headerFields;
  466. NonBodyFields m_trailerFields;
  467. FieldTypes m_fieldTypes;
  468. FieldToValue m_fieldValues;
  469. FieldToName m_fieldNames;
  470. NameToField m_names;
  471. ValueToName m_valueNames;
  472. FieldToGroup m_groups;
  473. MsgFields m_dataFields;
  474. };
  475. }
  476. #endif //FIX_DATADICTIONARY_H