private void PopulateMsgElements(string version, string msgType, FixMessage msg) { VfxFixVxRecord vxDetails = _vxRegistry.Get(version); if (vxDetails != null) { FixDxCollection msgElements = null; foreach (VfxFixVersion_Dictionary_Reference dxEntry in vxDetails.Dictionaries) { // REC: Retrieve the dictionary associated with // the version definition: FixDictionary dxInstance = _dxRegistry.GetEntry(dxEntry.Name); // REC: Attempt to retrieve the specified message // type from the dictionary: FixDxMessage dxMessage = dxInstance.GetMessageByType(msgType); if (dxMessage != null) { msgElements = dxInstance.Resolve(dxMessage.Elements); break; } } if (msgElements != null) { // REC: Create the sort ordering for the elements // and populate any fields and groups that have been // registered with the assembler: Collection <int> ordering = new Collection <int>(); foreach (IFixDxElement dxElement in msgElements) { ordering.Add(dxElement.Tag); if (dxElement is FixDxResolvedField) { if (_mapFields.ContainsKey(dxElement.Tag)) { msg.Content.SetField(_mapFields[dxElement.Tag]); } } else { if (_mapGroups.ContainsKey(dxElement.Tag)) { msg.Content.AddGroup(_mapGroups[dxElement.Tag]); } } } // REC: Assign the sort ordering for the header // elements to the message's header: msg.Content.SetOrdering(ordering); } } }
/// <summary> /// The GetUniqueMessages method retrieves a collection which /// represents the set of all FIX message definitions found in /// the dictionaries associated with a specific version. /// </summary> /// <param name="version"> /// The name of the version definition that is to be used /// for looking up the FIX message definitions. /// </param> /// <returns> /// The collection of message definitions that represents /// the complete set of all of the field definitions in the /// dictionaries associated with the specified version. /// </returns> public FixDxCollection GetUniqueMessages(string version) { FixDxCollection result = new FixDxCollection(); if (_vxRegistry != null) { VfxFixVxRecord vxDetails = _vxRegistry.Get(version); if (vxDetails != null) { if (_dxRegistry != null) { // REC: Temporary map that is used to ensure there // is only one instance of each MsgType: Dictionary <string, FixDxMessage> mapMessages = new Dictionary <string, FixDxMessage>(); // REC: Iterate over all of the FIX dictionaries that // are associated with the version and build the list // of FIX field definitions from them: foreach (VfxFixVersion_Dictionary_Reference dxEntry in vxDetails.Dictionaries) { FixDictionary dxInstance = _dxRegistry.GetEntry(dxEntry.Name); if (dxInstance != null) { foreach (IFixDxElement dxElement in dxInstance.Messages) { FixDxMessage dxMessage = dxElement as FixDxMessage; if (dxMessage != null) { if (mapMessages.ContainsKey(dxMessage.MsgType) == false) { mapMessages.Add(dxMessage.MsgType, dxMessage); } else { mapMessages[dxMessage.MsgType] = dxMessage; } } } } } foreach (string key in mapMessages.Keys) { result.Add(mapMessages[key]); } } } } return(result); }
// REC: Validate an instance of the FixMessage class against // the header/message/trailer definition in the dictionaries: public List <FixValidationResult> Validate(FixMessage msg) { List <FixValidationResult> result = new List <FixValidationResult>(); // REC: Build a queue of all of the FIX elements that // are contained in the message: Queue <SrcField> srcFields = new Queue <SrcField>(); // REC: Add the elements that are in the message's // header to the queue of source fields: PopulateQueue(srcFields, msg.Header); // REC: Add the elements that are in the message's // body to the queue of source fields: PopulateQueue(srcFields, msg.Content); // REC: Add the elements that are in the message's // trailer to the queue of source fields: PopulateQueue(srcFields, msg.Trailer); // REC: Create the MsgLayout structure that defines // the layout of a message as it is defined in the // configured FIX dictionaries: MsgLayout msgLayout = new MsgLayout(); // REC: The message layout's header entries are // copied from the cached list of entries that is // created when the validator is configured: foreach (FixValidationResult hdrEntry in _cachedHeader) { msgLayout.Header.Add(hdrEntry.Clone() as FixValidationResult); } // REC: The message layout's content entries are // only configured if the corresponding message // type can be found in the dictionaries: FixField fldMsgType = msg.Header.GetField(35); if (fldMsgType != null) { string strMsgType = fldMsgType.Content; foreach (FixDictionary dx in _settings.Dictionaries) { FixDxMessage dxMessage = dx.GetMessageByType(strMsgType); if (dxMessage != null) { // REC: Expand the list of elements contained // in the message's definition and populate the // message layout element list with them: FixDxCollection msgElements = dx.Resolve(dxMessage.Elements); foreach (IFixDxElement msgElement in msgElements) { msgLayout.Message.Add(CreateResult(msgElement)); } break; } } } // REC: the message layout's trailer entries are // copied from the cached list of entries that is // created when the validator is configured: foreach (FixValidationResult trlEntry in _cachedTrailer) { msgLayout.Trailer.Add(trlEntry.Clone() as FixValidationResult); } // REC: After the message layout has been defined // the validator can compare the content of the // source message to the layout definition: return(ProcessElements(srcFields, msgLayout)); }
/// <summary> /// The CloneMessage method is invoked to create a copy of /// an instance of a message definition. /// </summary> /// <param name="source"> /// The message definition to be duplicated. /// </param> /// <returns> /// The resulting clone of the supplied message. /// </returns> private FixDxMessage CloneMessage(FixDxMessage source) { FixDxMessage result = new FixDxMessage(source.MsgType, source.Name, source.MsgCategory); foreach(IFixDxElement dxElement in source.Elements) { result.Elements.Add(CloneElement(dxElement)); } return result; }
/// <summary> /// The AddMessage method adds a new instance of a /// message definition to the dictionary. /// </summary> /// <param name="dxMessage"> /// The FIX message definition that is to be added /// to the dictionary. /// </param> public void AddMessage(FixDxMessage dxMessage) { if (_mapMessagesByName.ContainsKey(dxMessage.Name)) { string error = string.Format("Dictionary already contains a message named {0}.", dxMessage.Name); throw new ArgumentException(error); } if (_mapMessagesByType.ContainsKey(dxMessage.MsgType)) { string error = string.Format("Dictionary already contains a message type {0}.", dxMessage.MsgType); throw new ArgumentException(error); } _messages.Add(dxMessage); _mapMessagesByType.Add(dxMessage.MsgType, dxMessage); _mapMessagesByName.Add(dxMessage.Name, dxMessage); }
/// <summary> /// The PopulateMessages method populates the message section /// of the supplied VFX dictionary with all message definitions /// that are found in the supplied XML dictionary. /// </summary> /// <param name="source"> /// The source dictionary for the message elements. /// </param> /// <param name="target"> /// The target dictionary for the converted elements. /// </param> private static void PopulateMessages(XmlDictionary source, FixDictionary target) { foreach (XmlFixDxMessage src in source.Messages.Entries) { FixDxMessage dst = new FixDxMessage(src.MsgType, src.Name, src.MsgCategory); foreach (IFixDxElement dxElement in TranslateElements(src.Elements)) { dst.Elements.Add(dxElement); } target.AddMessage(dst); } }