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

/home/orenmnero/autobuild/quickfix/src/C++/DataDictionary.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_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   // storage functions
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;
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, TYPE::Type type )
00182   {
00183     m_fieldTypes[ field ] = type;
00184   }
00185 
00186   bool getFieldType( int field, 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( !isMultipleValueStringField( field ) )
00223       return i->second.find( value ) != i->second.end();
00224 
00225     // MultipleValueString
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 isMultipleValueStringField( int field ) const
00273   {
00274     FieldTypes::const_iterator i = m_fieldTypes.find( field );
00275     return i != m_fieldTypes.end() && i->second == TYPE::MultipleValueString;
00276   }
00277 
00278   void checkFieldsOutOfOrder( bool value )
00279   { m_checkFieldsOutOfOrder = value; }
00280   void checkFieldsHaveValues( bool value )
00281   { m_checkFieldsHaveValues = value; }
00282   void checkUserDefinedFields( bool value )
00283   { m_checkUserDefinedFields = value; }
00284 
00286   void validate( const Message& message ) throw( std::exception );
00287   DataDictionary& operator=( const DataDictionary& rhs );
00288 
00289 private:
00291   void iterate( const FieldMap& map, const MsgType& msgType );
00292 
00294   void checkMsgType( const MsgType& msgType ) const
00295   {
00296     if ( !isMsgType( msgType.getValue() ) )
00297       throw InvalidMessageType();
00298   }
00299 
00301   bool shouldCheckTag( const FieldBase& field ) const
00302   {
00303     if( !m_checkUserDefinedFields && field.getField() >= FIELD::UserMin )
00304       return false;
00305     else
00306       return true;
00307   }
00308 
00310   void checkValidTagNumber( const FieldBase& field ) const
00311   throw( InvalidTagNumber )
00312   {
00313     if( m_fields.find( field.getField() ) == m_fields.end() )
00314       throw InvalidTagNumber( field.getField() );
00315   }
00316 
00317   void checkValidFormat( const FieldBase& field ) const
00318   throw( IncorrectDataFormat )
00319   {
00320     try
00321     {
00322       TYPE::Type type = TYPE::Unknown;
00323       getFieldType( field.getField(), type );
00324       switch ( type )
00325       {
00326       case TYPE::String:
00327         STRING_CONVERTOR::convert( field.getString() ); break;
00328       case TYPE::Char:
00329         CHAR_CONVERTOR::convert( field.getString() ); break;
00330       case TYPE::Price:
00331         PRICE_CONVERTOR::convert( field.getString() ); break;
00332       case TYPE::Int:
00333         INT_CONVERTOR::convert( field.getString() ); break;
00334       case TYPE::Amt:
00335         AMT_CONVERTOR::convert( field.getString() ); break;
00336       case TYPE::Qty:
00337         QTY_CONVERTOR::convert( field.getString() ); break;
00338       case TYPE::Currency:
00339         CURRENCY_CONVERTOR::convert( field.getString() ); break;
00340       case TYPE::MultipleValueString:
00341         MULTIPLEVALUESTRING_CONVERTOR::convert( field.getString() ); break;
00342       case TYPE::Exchange:
00343         EXCHANGE_CONVERTOR::convert( field.getString() ); break;
00344       case TYPE::UtcTimeStamp:
00345         UTCTIMESTAMP_CONVERTOR::convert( field.getString() ); break;
00346       case TYPE::Boolean:
00347         BOOLEAN_CONVERTOR::convert( field.getString() ); break;
00348       case TYPE::LocalMktDate:
00349         LOCALMKTDATE_CONVERTOR::convert( field.getString() ); break;
00350       case TYPE::Data:
00351         DATA_CONVERTOR::convert( field.getString() ); break;
00352       case TYPE::Float:
00353         FLOAT_CONVERTOR::convert( field.getString() ); break;
00354       case TYPE::PriceOffset:
00355         PRICEOFFSET_CONVERTOR::convert( field.getString() ); break;
00356       case TYPE::MonthYear:
00357         MONTHYEAR_CONVERTOR::convert( field.getString() ); break;
00358       case TYPE::DayOfMonth:
00359         DAYOFMONTH_CONVERTOR::convert( field.getString() ); break;
00360       case TYPE::UtcDate:
00361         UTCDATE_CONVERTOR::convert( field.getString() ); break;
00362       case TYPE::UtcTimeOnly:
00363         UTCTIMEONLY_CONVERTOR::convert( field.getString() ); break;
00364       case TYPE::NumInGroup:
00365         NUMINGROUP_CONVERTOR::convert( field.getString() ); break;
00366       case TYPE::Percentage:
00367         PERCENTAGE_CONVERTOR::convert( field.getString() ); break;
00368       case TYPE::SeqNum:
00369         SEQNUM_CONVERTOR::convert( field.getString() ); break;
00370       case TYPE::Length:
00371         LENGTH_CONVERTOR::convert( field.getString() ); break;
00372       case TYPE::Country:
00373         COUNTRY_CONVERTOR::convert( field.getString() ); break;
00374       case TYPE::Unknown: break;
00375       }
00376     }
00377     catch ( FieldConvertError& )
00378     { throw IncorrectDataFormat( field.getField() ); }
00379   }
00380 
00381   void checkValue( const FieldBase& field ) const
00382   throw( IncorrectTagValue )
00383   {
00384     if ( !hasFieldValue( field.getField() ) ) return ;
00385 
00386     const std::string& value = field.getString();
00387     if ( !isFieldValue( field.getField(), value ) )
00388       throw IncorrectTagValue( field.getField() );
00389   }
00390 
00392   void checkHasValue( const FieldBase& field ) const
00393   throw( NoTagValue )
00394   {
00395     if ( m_checkFieldsHaveValues && !field.getString().length() )
00396       throw NoTagValue( field.getField() );
00397   }
00398 
00400   void checkIsInMessage
00401   ( const FieldBase& field, const MsgType& msgType ) const
00402   throw( TagNotDefinedForMessage )
00403   {
00404     if ( !isMsgField( msgType, field.getField() ) )
00405       throw TagNotDefinedForMessage( field.getField() );
00406   }
00407 
00409   void checkGroupCount
00410   ( const FieldBase& field, const FieldMap& fieldMap, const MsgType& msgType ) const
00411   throw( RepeatingGroupCountMismatch )
00412   {
00413     int fieldNum = field.getField();
00414     if( isGroup(msgType, fieldNum) )
00415     {
00416       if( fieldMap.groupCount(fieldNum)
00417         != IntConvertor::convert(field.getString()) )
00418       throw RepeatingGroupCountMismatch(fieldNum);
00419     }
00420   }
00421 
00423   void checkHasRequired
00424   ( const FieldMap& header, const FieldMap& body, const FieldMap& trailer,
00425     const MsgType& msgType ) const
00426   throw( RequiredTagMissing )
00427   {
00428     NonBodyFields::const_iterator iNBF;
00429     for( iNBF = m_headerFields.begin(); iNBF != m_headerFields.end(); ++iNBF )
00430     {
00431       if( iNBF->second == true && !header.isSetField(iNBF->first) )
00432         throw RequiredTagMissing( iNBF->first );
00433     }
00434 
00435     for( iNBF = m_trailerFields.begin(); iNBF != m_trailerFields.end(); ++iNBF )
00436     {
00437       if( iNBF->second == true && !trailer.isSetField(iNBF->first) )
00438         throw RequiredTagMissing( iNBF->first );
00439     }
00440 
00441     MsgTypeToField::const_iterator iM
00442       = m_requiredFields.find( msgType.getValue() );
00443     if ( iM == m_requiredFields.end() ) return ;
00444 
00445     const MsgFields& fields = iM->second;
00446     MsgFields::const_iterator iF;
00447     for( iF = fields.begin(); iF != fields.end(); ++iF )
00448     {
00449       if( !body.isSetField(*iF) )
00450         throw RequiredTagMissing( *iF );
00451     }
00452 
00453     FieldMap::g_iterator groups;
00454     for( groups = body.g_begin(); groups != body.g_end(); ++groups )
00455     {
00456       int delim;
00457       const DataDictionary* DD = 0;
00458       int field = groups->first;
00459       if( getGroup( msgType.getValue(), field, delim, DD ) )
00460       {
00461         std::vector<FieldMap*>::const_iterator group;
00462         for( group = groups->second.begin(); group != groups->second.end(); ++group )
00463           DD->checkHasRequired( **group, **group, **group, msgType );
00464       }
00465     }
00466   }
00467 
00469   void readMSXMLDOM( const std::string& );
00470   void readMSXML( const std::string& );
00472   void readLibXml( const std::string& );
00473 
00474   int lookupXMLFieldNumber( DOMDocument*, DOMNode* ) const;
00475   int lookupXMLFieldNumber( DOMDocument*, const std::string& name ) const;
00476   int addXMLComponentFields( DOMDocument*, DOMNode*, const std::string& msgtype, DataDictionary&, bool );
00477   void addXMLGroup( DOMDocument*, DOMNode*, const std::string& msgtype, DataDictionary&, bool );
00478   TYPE::Type XMLTypeToType( const std::string& xmlType ) const;
00479 
00480   bool m_hasVersion;
00481   bool m_checkFieldsOutOfOrder;
00482   bool m_checkFieldsHaveValues;
00483   bool m_checkUserDefinedFields;
00484   BeginString m_beginString;
00485   MsgTypeToField m_messageFields;
00486   MsgTypeToField m_requiredFields;
00487   MsgTypes m_messages;
00488   Fields m_fields;
00489   OrderedFields m_orderedFields;
00490   mutable OrderedFieldsArray m_orderedFieldsArray;
00491   NonBodyFields m_headerFields;
00492   NonBodyFields m_trailerFields;
00493   FieldTypes m_fieldTypes;
00494   FieldToValue m_fieldValues;
00495   FieldToName m_fieldNames;
00496   NameToField m_names;
00497   ValueToName m_valueNames;
00498   FieldToGroup m_groups;
00499 };
00500 }
00501 
00502 #endif //FIX_DATADICTIONARY_H

Generated on Mon Jul 24 19:36:27 2006 for QuickFIX by doxygen 1.3.6-20040222 written by Dimitri van Heesch, © 1997-2001