// REC: The ProcessElements method compares the contents // of a message to the corresponding message layout and // returns a list of validation result entries for each // of the fields that were encountered in the message: private List <FixValidationResult> ProcessElements(Queue <SrcField> queue, MsgLayout layout) { List <FixValidationResult> result = new List <FixValidationResult>(); int hdrIndex = 0; int msgIndex = 0; int trlIndex = 0; while (queue.Count > 0) { bool processed = false; // REC: Retrieve the next source field from // the sequential queue of message fields: SrcField current = queue.Dequeue(); // REC: Scan the result set for a placeholder // for this field before checking the template: bool fieldOOS = false; foreach (FixValidationResult fvr in result) { // REC: If the current field's tag matches the // tag in the validation result, and the result's // validation code is set to Field_Missing, then // the result entry is a placeholder for the field: if (fvr.ResultCode == FixValidationCode.Field_Missing) { if (current.Tag == fvr.FieldTag) { // REC: The fact that this entry is a placeholder // means that it was previously passed over when // a field was being matched. This means that the // current field is out of sequence, or it would // already be in the validation result set: fvr.FieldValue = current.Value; fvr.ResultCode = FixValidationCode.Field_Present; fvr.ResultText = "Field Present"; if (fieldOOS == true) { fvr.ResultCode = FixValidationCode.Field_OOS; fvr.ResultText = "Out of Sequence"; } //VerifyFieldType(current, fvr); if (fvr.Nodes.Count > 0) { fvr.Nodes = ValidateGroup(queue, fvr); } // REC: Remove the validation result from its // current position in the result set... result.Remove(fvr); // REC: ...and add it to the end of the result // set since that's where it was encountered in // the source message: result.Add(fvr); // REC: Set the processed flag to true to indicate // that this field in the source message has now // been completely processed: processed = true; break; } else { // REC: The field is missing, but it doesn't match // the current one. If the missing field is also a // required field, then set the OOS flag: if (fvr.FieldRequired == true) { fieldOOS = true; } } } } // REC: If the current field in the message wasn't found // in the result set, as a placeholder, then scan the // elements in the message header for a match: if (processed == false) { while (hdrIndex != layout.Header.Count) { // REC: Create a copy of the entry in the // message header layout: FixValidationResult src = layout.Header[hdrIndex++]; FixValidationResult dst = src.Clone() as FixValidationResult; // REC: Add the copy of the entry to the // result set in anticipation of the field // being matched. If it's not matched, then // the entry will act as a placeholder: result.Add(dst); if (current.Tag == src.FieldTag) { dst.FieldValue = current.Value; dst.ResultCode = FixValidationCode.Field_Present; dst.ResultText = "Field Present"; // REC: If the entry in the layout is a // repeating group header, then attempt // to validate as many instances of the // repeating group as are indicated by // the value of in the message's field: if (src.Nodes.Count > 0) { dst.Nodes = ValidateGroup(queue, dst); dst.ResultCode = FixValidationCode.Group_Present; dst.ResultText = "Group Present"; } processed = true; } } // REC: If the current field wasn't found in the // result set, or in the layout for the message's // header elements, then attempt to locate it in // the message's content elements: if (processed == false) { while (msgIndex != layout.Message.Count) { FixValidationResult src = layout.Message[msgIndex++]; FixValidationResult dst = src.Clone() as FixValidationResult; // REC: Add the copy of the entry to the // result set in anticipation of the field // being matched. If it's not matched, then // the entry will act as a placeholder: result.Add(dst); if (current.Tag == src.FieldTag) { dst.FieldValue = current.Value; dst.ResultCode = FixValidationCode.Field_Present; dst.ResultText = "Field Present"; // REC: If the entry in the layout is a // repeating group header, then attempt // to validate as many instances of the // repeating group as are indicated by // the value of in the message's field: if (src.Nodes.Count > 0) { dst.Nodes = ValidateGroup(queue, dst); dst.ResultCode = FixValidationCode.Group_Present; dst.ResultText = "Group Present"; } processed = true; break; } } } // REC: If the field wasn't found in the header // or in the body, then scan the message trailer: if (processed == false) { // REC: Note that the trailer elements don't // get copied into the result set unless there // is a match for one of them; these elements // should always be placed at the end of the // result set if there is no match for them: for (int i = trlIndex; i != layout.Trailer.Count; i++) { if (current.Tag == layout.Trailer[i].FieldTag) { while (trlIndex != layout.Trailer.Count) { FixValidationResult src = layout.Trailer[trlIndex++]; FixValidationResult dst = src.Clone() as FixValidationResult; result.Add(dst); if (current.Tag == src.FieldTag) { dst.FieldValue = current.Value; dst.ResultCode = FixValidationCode.Field_Present; dst.ResultText = "Field Present"; if (src.Nodes.Count > 0) { dst.Nodes = ValidateGroup(queue, dst); dst.ResultCode = FixValidationCode.Group_Present; dst.ResultText = "Group Present"; } processed = true; break; } } } } // REC: If the field wasn't found in the trailer // layout, then it's a UDF and can just be added // to the result set where it's found: if (processed == false) { FixValidationResult dst = new FixValidationResult(); dst.FieldTag = current.Tag; dst.FieldName = current.Name; dst.FieldValue = current.Value; dst.ResultCode = FixValidationCode.Field_Present; dst.ResultText = "User-defined Field"; result.Add(dst); } } } } return(result); }
// REC: The ProcessElements method compares the contents // of a message to the corresponding message layout and // returns a list of validation result entries for each // of the fields that were encountered in the message: private List<FixValidationResult> ProcessElements(Queue<SrcField> queue, MsgLayout layout) { List<FixValidationResult> result = new List<FixValidationResult>(); int hdrIndex = 0; int msgIndex = 0; int trlIndex = 0; while (queue.Count > 0) { bool processed = false; // REC: Retrieve the next source field from // the sequential queue of message fields: SrcField current = queue.Dequeue(); // REC: Scan the result set for a placeholder // for this field before checking the template: bool fieldOOS = false; foreach (FixValidationResult fvr in result) { // REC: If the current field's tag matches the // tag in the validation result, and the result's // validation code is set to Field_Missing, then // the result entry is a placeholder for the field: if (fvr.ResultCode == FixValidationCode.Field_Missing) { if (current.Tag == fvr.FieldTag) { // REC: The fact that this entry is a placeholder // means that it was previously passed over when // a field was being matched. This means that the // current field is out of sequence, or it would // already be in the validation result set: fvr.FieldValue = current.Value; fvr.ResultCode = FixValidationCode.Field_Present; fvr.ResultText = "Field Present"; if (fieldOOS == true) { fvr.ResultCode = FixValidationCode.Field_OOS; fvr.ResultText = "Out of Sequence"; } //VerifyFieldType(current, fvr); if (fvr.Nodes.Count > 0) { fvr.Nodes = ValidateGroup(queue, fvr); } // REC: Remove the validation result from its // current position in the result set... result.Remove(fvr); // REC: ...and add it to the end of the result // set since that's where it was encountered in // the source message: result.Add(fvr); // REC: Set the processed flag to true to indicate // that this field in the source message has now // been completely processed: processed = true; break; } else { // REC: The field is missing, but it doesn't match // the current one. If the missing field is also a // required field, then set the OOS flag: if (fvr.FieldRequired == true) { fieldOOS = true; } } } } // REC: If the current field in the message wasn't found // in the result set, as a placeholder, then scan the // elements in the message header for a match: if(processed == false) { while(hdrIndex != layout.Header.Count) { // REC: Create a copy of the entry in the // message header layout: FixValidationResult src = layout.Header[hdrIndex++]; FixValidationResult dst = src.Clone() as FixValidationResult ; // REC: Add the copy of the entry to the // result set in anticipation of the field // being matched. If it's not matched, then // the entry will act as a placeholder: result.Add(dst) ; if(current.Tag == src.FieldTag) { dst.FieldValue = current.Value; dst.ResultCode = FixValidationCode.Field_Present; dst.ResultText = "Field Present" ; // REC: If the entry in the layout is a // repeating group header, then attempt // to validate as many instances of the // repeating group as are indicated by // the value of in the message's field: if(src.Nodes.Count > 0) { dst.Nodes = ValidateGroup(queue, dst) ; dst.ResultCode = FixValidationCode.Group_Present; dst.ResultText = "Group Present"; } processed = true ; } } // REC: If the current field wasn't found in the // result set, or in the layout for the message's // header elements, then attempt to locate it in // the message's content elements: if(processed == false) { while(msgIndex != layout.Message.Count) { FixValidationResult src = layout.Message[msgIndex++] ; FixValidationResult dst = src.Clone() as FixValidationResult ; // REC: Add the copy of the entry to the // result set in anticipation of the field // being matched. If it's not matched, then // the entry will act as a placeholder: result.Add(dst) ; if(current.Tag == src.FieldTag) { dst.FieldValue = current.Value ; dst.ResultCode = FixValidationCode.Field_Present; dst.ResultText = "Field Present" ; // REC: If the entry in the layout is a // repeating group header, then attempt // to validate as many instances of the // repeating group as are indicated by // the value of in the message's field: if(src.Nodes.Count > 0) { dst.Nodes = ValidateGroup(queue, dst) ; dst.ResultCode = FixValidationCode.Group_Present; dst.ResultText = "Group Present" ; } processed = true ; break ; } } } // REC: If the field wasn't found in the header // or in the body, then scan the message trailer: if(processed == false) { // REC: Note that the trailer elements don't // get copied into the result set unless there // is a match for one of them; these elements // should always be placed at the end of the // result set if there is no match for them: for(int i=trlIndex; i!=layout.Trailer.Count; i++) { if(current.Tag == layout.Trailer[i].FieldTag) { while (trlIndex != layout.Trailer.Count) { FixValidationResult src = layout.Trailer[trlIndex++]; FixValidationResult dst = src.Clone() as FixValidationResult; result.Add(dst); if (current.Tag == src.FieldTag) { dst.FieldValue = current.Value; dst.ResultCode = FixValidationCode.Field_Present; dst.ResultText = "Field Present"; if (src.Nodes.Count > 0) { dst.Nodes = ValidateGroup(queue, dst); dst.ResultCode = FixValidationCode.Group_Present; dst.ResultText = "Group Present"; } processed = true; break; } } } } // REC: If the field wasn't found in the trailer // layout, then it's a UDF and can just be added // to the result set where it's found: if (processed == false) { FixValidationResult dst = new FixValidationResult(); dst.FieldTag = current.Tag; dst.FieldName = current.Name; dst.FieldValue = current.Value; dst.ResultCode = FixValidationCode.Field_Present; dst.ResultText = "User-defined Field"; result.Add(dst); } } } } 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)); }
// 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); }