00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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