diff --git a/AcceptanceTest/TestBase.cs b/AcceptanceTest/TestBase.cs
index 6806c789d..07acedab8 100644
--- a/AcceptanceTest/TestBase.cs
+++ b/AcceptanceTest/TestBase.cs
@@ -23,7 +23,7 @@ public void Setup()
ILogFactory? logFactory = settings.Get().Has("Verbose") && settings.Get().GetBool("Verbose")
? new FileLogFactory(settings)
- : null;
+ : new NullLogFactory();
_acceptor = new ThreadedSocketAcceptor(testApp, storeFactory, settings, logFactory);
@@ -43,4 +43,4 @@ protected void RunTest(string definitionPath)
using StreamReader sr = new(definitionPath);
runner.Run(sr);
}
-}
\ No newline at end of file
+}
diff --git a/Examples/FixToJson/Examples.FixToJson.csproj b/Examples/FixToJson/Examples.FixToJson.csproj
index 2a3da6645..f5a698af4 100644
--- a/Examples/FixToJson/Examples.FixToJson.csproj
+++ b/Examples/FixToJson/Examples.FixToJson.csproj
@@ -3,11 +3,9 @@
Exe
net6.0
- FixToJson
- FixToJson
+ enable
Copyright © Connamara Systems, LLC 2022
Connamara Systems, LLC
- AnyCPU;x64
false
diff --git a/Examples/FixToJson/Program.cs b/Examples/FixToJson/Program.cs
index a5540c149..2142ba359 100644
--- a/Examples/FixToJson/Program.cs
+++ b/Examples/FixToJson/Program.cs
@@ -1,12 +1,15 @@
using System;
-using System.Text;
using System.IO;
-namespace TradeClient
+namespace Examples.FixToJson
{
- class Program
+ internal static class Program
{
- static void FixToJson(string fname, bool humanReadableValues, QuickFix.DataDictionary.DataDictionary sessionDataDictionary, QuickFix.DataDictionary.DataDictionary appDataDictionary)
+ static void FixToJson(
+ string fname,
+ bool humanReadableValues,
+ QuickFix.DataDictionary.DataDictionary? sessionDataDictionary,
+ QuickFix.DataDictionary.DataDictionary? appDataDictionary)
{
try
{
@@ -15,20 +18,19 @@ static void FixToJson(string fname, bool humanReadableValues, QuickFix.DataDicti
{
QuickFix.IMessageFactory msgFactory = new QuickFix.DefaultMessageFactory();
QuickFix.Message msg = new QuickFix.Message();
- string line = null;
string comma = "";
- while ((line = streamReader.ReadLine()) != null)
+ while (streamReader.ReadLine() is { } line)
{
line = line.Trim();
msg.FromString(line, false, sessionDataDictionary, appDataDictionary, msgFactory);
- Console.WriteLine(comma + msg.ToJSON(humanReadableValues));
+ Console.WriteLine(comma + msg.ToJSON(humanReadableValues: humanReadableValues));
comma = ",";
}
}
Console.WriteLine("]\n}");
}
- catch (System.Exception e)
+ catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
@@ -40,27 +42,27 @@ static void Main(string[] args)
{
if (args.Length < 1 || args.Length > 4)
{
- System.Console.WriteLine("USAGE");
- System.Console.WriteLine("");
- System.Console.WriteLine(" FixToJson.exe FILE [HUMAN_READABLE_VALUES] [DATA_DICTIONARY]");
- System.Console.WriteLine("");
- System.Console.WriteLine("EXAMPLES");
- System.Console.WriteLine("");
- System.Console.WriteLine(" FixToJson.exe messages.log true ../../spec/fix/FIX50SP2.xml");
- System.Console.WriteLine(" FixToJson.exe messages.log true ../../spec/fix/FIX44.xml");
- System.Console.WriteLine(" FixToJson.exe messages.log false ../../spec/fix/FIX42.xml");
- System.Console.WriteLine("");
- System.Console.WriteLine("NOTE");
- System.Console.WriteLine("");
- System.Console.WriteLine(" Per the FIX JSON Encoding Specification, tags are converted to human-readable form, but values are not.");
- System.Console.WriteLine(" Set the HUMAN_READABLE_VALUES argument to TRUE to override the standard behavior.");
- System.Environment.Exit(2);
+ Console.WriteLine("USAGE");
+ Console.WriteLine("");
+ Console.WriteLine(" FixToJson.exe FILE [HUMAN_READABLE_VALUES] [DATA_DICTIONARY]");
+ Console.WriteLine("");
+ Console.WriteLine("EXAMPLES");
+ Console.WriteLine("");
+ Console.WriteLine(" FixToJson.exe messages.log true ../../spec/fix/FIX50SP2.xml");
+ Console.WriteLine(" FixToJson.exe messages.log true ../../spec/fix/FIX44.xml");
+ Console.WriteLine(" FixToJson.exe messages.log false ../../spec/fix/FIX42.xml");
+ Console.WriteLine("");
+ Console.WriteLine("NOTE");
+ Console.WriteLine("");
+ Console.WriteLine(" Per the FIX JSON Encoding Specification, tags are converted to human-readable form, but values are not.");
+ Console.WriteLine(" Set the HUMAN_READABLE_VALUES argument to TRUE to override the standard behavior.");
+ Environment.Exit(2);
}
string fname = args[0];
bool humanReadableValues = false;
- QuickFix.DataDictionary.DataDictionary sessionDataDictionary = null;
- QuickFix.DataDictionary.DataDictionary appDataDictionary = null;
+ QuickFix.DataDictionary.DataDictionary? sessionDataDictionary = null;
+ QuickFix.DataDictionary.DataDictionary? appDataDictionary = null;
if (args.Length > 1)
{
diff --git a/Examples/JsonToFix/Examples.JsonToFix.csproj b/Examples/JsonToFix/Examples.JsonToFix.csproj
index b7e62dea4..f5a698af4 100644
--- a/Examples/JsonToFix/Examples.JsonToFix.csproj
+++ b/Examples/JsonToFix/Examples.JsonToFix.csproj
@@ -3,7 +3,6 @@
Exe
net6.0
- enable
enable
Copyright © Connamara Systems, LLC 2022
Connamara Systems, LLC
diff --git a/Examples/JsonToFix/Program.cs b/Examples/JsonToFix/Program.cs
index e33c3bee8..38655445f 100644
--- a/Examples/JsonToFix/Program.cs
+++ b/Examples/JsonToFix/Program.cs
@@ -1,12 +1,11 @@
using System;
-using System.Text;
-using System.Text.Json;
using System.IO;
+using System.Text.Json;
using QuickFix;
-namespace TradeClient
+namespace Examples.JsonToFix
{
- class Program
+ internal static class Program
{
static void JsonMsgToFix(string json, QuickFix.DataDictionary.DataDictionary sessionDataDictionary, QuickFix.DataDictionary.DataDictionary appDataDictionary, QuickFix.IMessageFactory msgFactory)
{
@@ -36,7 +35,7 @@ static void JsonToFix(string fname, QuickFix.DataDictionary.DataDictionary sessi
}
}
}
- catch (System.Exception e)
+ catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
@@ -48,22 +47,22 @@ static void Main(string[] args)
{
if (args.Length < 1 || args.Length > 2)
{
- System.Console.WriteLine("USAGE");
- System.Console.WriteLine("");
- System.Console.WriteLine(" FixToJson.exe FILE DATA_DICTIONARY");
- System.Console.WriteLine("");
- System.Console.WriteLine(" The FILE may contain either a single message in FIX JSON Encoding, or an array of messages in a root-level \"messages\" element.");
- System.Console.WriteLine("");
- System.Console.WriteLine("EXAMPLES");
- System.Console.WriteLine("");
- System.Console.WriteLine(" JsonToFix.exe messages.json ../../spec/fix/FIX50SP2.xml");
- System.Console.WriteLine(" JsonToFix.exe messages.json ../../spec/fix/FIX44.xml");
- System.Console.WriteLine(" JsonToFix.exe messages.json ../../spec/fix/FIX42.xml");
- System.Console.WriteLine("");
- System.Console.WriteLine("NOTE");
- System.Console.WriteLine("");
- System.Console.WriteLine(" Per the FIX JSON Encoding Specification, tags are converted to human-readable form, but values are not.");
- System.Environment.Exit(2);
+ Console.WriteLine("USAGE");
+ Console.WriteLine("");
+ Console.WriteLine(" FixToJson.exe FILE DATA_DICTIONARY");
+ Console.WriteLine("");
+ Console.WriteLine(" The FILE may contain either a single message in FIX JSON Encoding, or an array of messages in a root-level \"messages\" element.");
+ Console.WriteLine("");
+ Console.WriteLine("EXAMPLES");
+ Console.WriteLine("");
+ Console.WriteLine(" JsonToFix.exe messages.json ../../spec/fix/FIX50SP2.xml");
+ Console.WriteLine(" JsonToFix.exe messages.json ../../spec/fix/FIX44.xml");
+ Console.WriteLine(" JsonToFix.exe messages.json ../../spec/fix/FIX42.xml");
+ Console.WriteLine("");
+ Console.WriteLine("NOTE");
+ Console.WriteLine("");
+ Console.WriteLine(" Per the FIX JSON Encoding Specification, tags are converted to human-readable form, but values are not.");
+ Environment.Exit(2);
}
string fname = args[0];
diff --git a/QuickFIXn/DataDictionary/DataDictionary.cs b/QuickFIXn/DataDictionary/DataDictionary.cs
index d19bdfe99..2bc866859 100644
--- a/QuickFIXn/DataDictionary/DataDictionary.cs
+++ b/QuickFIXn/DataDictionary/DataDictionary.cs
@@ -90,8 +90,7 @@ public static void Validate(Message message, DataDictionary sessionDataDict, Dat
if (((null != sessionDataDict) && sessionDataDict.CheckFieldsOutOfOrder) || ((null != appDataDict) && appDataDict.CheckFieldsOutOfOrder))
{
- int field;
- if (!message.HasValidStructure(out field))
+ if (!message.HasValidStructure(out var field))
throw new TagOutOfOrder(field);
}
diff --git a/QuickFIXn/Fields/IField.cs b/QuickFIXn/Fields/IField.cs
index 3935a446a..b8eb97d17 100644
--- a/QuickFIXn/Fields/IField.cs
+++ b/QuickFIXn/Fields/IField.cs
@@ -1,4 +1,5 @@
-namespace QuickFix.Fields
+#nullable enable
+namespace QuickFix.Fields
{
///
/// Interface for all field classes
@@ -29,4 +30,4 @@ public abstract class IField
///
public abstract int getTotal();
}
-}
\ No newline at end of file
+}
diff --git a/QuickFIXn/Message/FieldMap.cs b/QuickFIXn/Message/FieldMap.cs
index 06c62adfb..256d4e938 100644
--- a/QuickFIXn/Message/FieldMap.cs
+++ b/QuickFIXn/Message/FieldMap.cs
@@ -1,4 +1,5 @@
-using System;
+#nullable enable
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -10,16 +11,27 @@ namespace QuickFix
///
/// Field container used by messages, groups, and composites
///
- public class FieldMap : IEnumerable>
- {
+ public class FieldMap : IEnumerable> {
+ private SortedDictionary _fields = new();
+
+ /// FIXME sorted dict is a hack to get quasi-correct field order
+ private Dictionary> _groups = new();
+
+ ///
+ /// order of field tags as an integer array
+ ///
+ public int[] FieldOrder { get; private set; } = Array.Empty();
+
+ ///
+ /// Used for validation. Only set during Message parsing.
+ ///
+ public List RepeatedTags { get; private set; } = new();
+
///
/// Default constructor
///
public FieldMap()
{
- _fields = new SortedDictionary(); // FIXME sorted dict is a hack to get quasi-correct field order
- _groups = new Dictionary>();
- this.RepeatedTags = new List();
}
///
@@ -29,10 +41,9 @@ public FieldMap()
public FieldMap(int[] fieldOrd)
: this()
{
- _fieldOrder = fieldOrd;
+ FieldOrder = fieldOrd;
}
-
///
/// FIXME this should probably make a deeper copy
///
@@ -45,33 +56,15 @@ public FieldMap(FieldMap src)
public void CopyStateFrom(FieldMap src)
{
- this._fieldOrder = src._fieldOrder;
+ FieldOrder = src.FieldOrder;
- this._fields = new SortedDictionary(src._fields);
+ _fields = new SortedDictionary(src._fields);
- this._groups = new Dictionary>();
+ _groups = new Dictionary>();
foreach (KeyValuePair> g in src._groups)
- this._groups.Add(g.Key, new List(g.Value));
-
- this.RepeatedTags = new List(src.RepeatedTags);
- }
-
- ///
- /// FieldOrder Property
- /// order of field tags as an integer array
- ///
- public int[] FieldOrder
- {
- get { return _fieldOrder; }
- }
+ _groups.Add(g.Key, new List(g.Value));
- ///
- /// QuickFIX-CPP compat, see FieldOrder property
- ///
- /// field order integer array
- public int[] getFieldOrder()
- {
- return _fieldOrder;
+ RepeatedTags = new List(src.RepeatedTags);
}
///
@@ -88,7 +81,7 @@ public bool RemoveField(int field)
/// set field in the fieldmap
/// will overwrite field if it exists
///
- public void SetField(Fields.IField field)
+ public void SetField(IField field)
{
_fields[field.Tag] = field;
}
@@ -96,7 +89,7 @@ public void SetField(Fields.IField field)
///
/// set many fields at the same time
///
- public void SetFields(IEnumerable fields)
+ public void SetFields(IEnumerable fields)
{
foreach (var field in fields)
{
@@ -109,8 +102,8 @@ public void SetFields(IEnumerable fields)
///
///
/// will overwrite existing field if set to true
- /// false if overwrite would be violated, else true
- public bool SetField(Fields.IField field, bool overwrite)
+ /// false if overwrite=true and is denied
+ public bool SetField(IField field, bool overwrite)
{
if (_fields.ContainsKey(field.Tag) && !overwrite)
return false;
@@ -125,7 +118,7 @@ public bool SetField(Fields.IField field, bool overwrite)
/// this field's tag is used to extract the value from the message; that value is saved back into this object
/// thrown if isn't found
///
- public Fields.BooleanField GetField(Fields.BooleanField field)
+ public BooleanField GetField(BooleanField field)
{
field.Obj = GetBoolean(field.Tag);
return field;
@@ -137,7 +130,7 @@ public Fields.BooleanField GetField(Fields.BooleanField field)
/// this field's tag is used to extract the value from the message; that value is saved back into this object
/// thrown if isn't found
///
- public Fields.StringField GetField(Fields.StringField field)
+ public StringField GetField(StringField field)
{
field.Obj = GetString(field.Tag);
return field;
@@ -149,7 +142,7 @@ public Fields.StringField GetField(Fields.StringField field)
/// this field's tag is used to extract the value from the message; that value is saved back into this object
/// thrown if isn't found
///
- public Fields.CharField GetField(Fields.CharField field)
+ public CharField GetField(CharField field)
{
field.Obj = GetChar(field.Tag);
return field;
@@ -161,7 +154,7 @@ public Fields.CharField GetField(Fields.CharField field)
/// this field's tag is used to extract the value from the message; that value is saved back into this object
/// thrown if isn't found
///
- public Fields.IntField GetField(Fields.IntField field)
+ public IntField GetField(IntField field)
{
field.Obj = GetInt(field.Tag);
return field;
@@ -173,7 +166,7 @@ public Fields.IntField GetField(Fields.IntField field)
/// this field's tag is used to extract the value from the message; that value is saved back into this object
/// thrown if isn't found
///
- public Fields.ULongField GetField(Fields.ULongField field)
+ public ULongField GetField(ULongField field)
{
field.Obj = GetULong(field.Tag);
return field;
@@ -185,7 +178,7 @@ public Fields.ULongField GetField(Fields.ULongField field)
/// this field's tag is used to extract the value from the message; that value is saved back into this object
/// thrown if isn't found
///
- public Fields.DecimalField GetField(Fields.DecimalField field)
+ public DecimalField GetField(DecimalField field)
{
field.Obj = GetDecimal(field.Tag);
return field;
@@ -197,7 +190,7 @@ public Fields.DecimalField GetField(Fields.DecimalField field)
/// this field's tag is used to extract the value from the message; that value is saved back into this object
/// thrown if isn't found
///
- public Fields.DateTimeField GetField(Fields.DateTimeField field)
+ public DateTimeField GetField(DateTimeField field)
{
field.Obj = GetDateTime(field.Tag);
return field;
@@ -209,7 +202,7 @@ public Fields.DateTimeField GetField(Fields.DateTimeField field)
/// this field's tag is used to extract the value from the message; that value is saved back into this object
/// thrown if isn't found
///
- public Fields.DateOnlyField GetField(Fields.DateOnlyField field)
+ public DateOnlyField GetField(DateOnlyField field)
{
field.Obj = GetDateOnly(field.Tag);
return field;
@@ -221,7 +214,7 @@ public Fields.DateOnlyField GetField(Fields.DateOnlyField field)
/// this field's tag is used to extract the value from the message; that value is saved back into this object
/// thrown if isn't found
///
- public Fields.TimeOnlyField GetField(Fields.TimeOnlyField field)
+ public TimeOnlyField GetField(TimeOnlyField field)
{
field.Obj = GetTimeOnly(field.Tag);
return field;
@@ -232,7 +225,7 @@ public Fields.TimeOnlyField GetField(Fields.TimeOnlyField field)
///
/// Field Object
/// true if set
- public bool IsSetField(Fields.IField field)
+ public bool IsSetField(IField field)
{
return IsSetField(field.Tag);
}
@@ -268,18 +261,16 @@ internal void AddGroup(Group grp, bool autoIncCounter)
// copy, in case user code reuses input object
Group group = grp.Clone();
- if (!_groups.ContainsKey(group.Field))
- _groups.Add(group.Field, new List());
- _groups[group.Field].Add(group);
+ if (!_groups.ContainsKey(group.CounterField))
+ _groups.Add(group.CounterField, new List());
+ _groups[group.CounterField].Add(group);
if (autoIncCounter)
{
// increment group size
- int groupsize = _groups[group.Field].Count;
- int counttag = group.Field;
- IntField count = null;
-
- count = new IntField(counttag, groupsize);
+ int groupsize = _groups[group.CounterField].Count;
+ int counttag = group.CounterField;
+ IntField count = new IntField(counttag, groupsize);
this.SetField(count, true);
}
}
@@ -304,18 +295,15 @@ public Group GetGroup(int num, int field)
return _groups[field][num - 1];
}
- //TODO v2: change this to return void
///
/// Extracts a repeating-group item into
///
/// index of desired group item (index starts at 1, not 0)
/// group to populate (group.Field is used by this function to extract the group)
- /// A redundant reference to Do not use this. This method will be changed to return void in a future release.
- public Group GetGroup(int num, Group group)
+ public void GetGroup(int num, Group group)
{
- int tag = group.Field;
+ int tag = group.CounterField;
group.CopyStateFrom(this.GetGroup(num, tag));
- return group;
}
///
@@ -326,15 +314,11 @@ public Group GetGroup(int num, Group group)
///
public int GetInt(int tag)
{
- if (!_fields.TryGetValue(tag, out IField fld))
- {
+ if (!_fields.TryGetValue(tag, out IField? fld))
throw new FieldNotFoundException(tag);
- }
if (fld is FieldBase intField)
- {
return intField.Obj;
- }
return IntConverter.Convert(fld.ToString());
}
@@ -349,11 +333,10 @@ public ulong GetULong(int tag)
{
try
{
- Fields.IField fld = _fields[tag];
+ IField fld = _fields[tag];
if (fld.GetType() == typeof(ULongField))
return ((ULongField)fld).Obj;
- else
- return ULongConverter.Convert(fld.ToString());
+ return ULongConverter.Convert(fld.ToString());
}
catch (System.Collections.Generic.KeyNotFoundException)
{
@@ -369,27 +352,16 @@ public ulong GetULong(int tag)
///
public DateTime GetDateTime(int tag)
{
- if (!_fields.TryGetValue(tag, out IField fld))
- {
+ if (!_fields.TryGetValue(tag, out IField? fld))
throw new FieldNotFoundException(tag);
- }
-
- if (fld is DateOnlyField dateOnlyField)
- {
- return dateOnlyField.Obj.Date;
- }
- if (fld is TimeOnlyField timeOnlyField)
- {
- return new DateTime(1980, 01, 01).Add(timeOnlyField.Obj.TimeOfDay);
- }
-
- if (fld is FieldBase dateTimeField)
+ return fld switch
{
- return dateTimeField.Obj;
- }
-
- return DateTimeConverter.ConvertToDateTime(fld.ToString());
+ DateOnlyField dateOnlyField => dateOnlyField.Obj.Date,
+ TimeOnlyField timeOnlyField => new DateTime(1980, 01, 01).Add(timeOnlyField.Obj.TimeOfDay),
+ FieldBase dateTimeField => dateTimeField.Obj,
+ _ => DateTimeConverter.ConvertToDateTime(fld.ToString())
+ };
}
///
@@ -400,15 +372,11 @@ public DateTime GetDateTime(int tag)
///
public DateTime GetDateOnly(int tag)
{
- if (!_fields.TryGetValue(tag, out IField fld))
- {
+ if (!_fields.TryGetValue(tag, out IField? fld))
throw new FieldNotFoundException(tag);
- }
if (fld is FieldBase dateTimeField)
- {
return dateTimeField.Obj.Date;
- }
return DateTimeConverter.ConvertToDateOnly(fld.ToString());
}
@@ -421,15 +389,11 @@ public DateTime GetDateOnly(int tag)
///
public DateTime GetTimeOnly(int tag)
{
- if (!_fields.TryGetValue(tag, out IField fld))
- {
+ if (!_fields.TryGetValue(tag, out IField? fld))
throw new FieldNotFoundException(tag);
- }
if (fld is FieldBase dateTimeField)
- {
return new DateTime(1980, 01, 01).Add(dateTimeField.Obj.TimeOfDay);
- }
return DateTimeConverter.ConvertToTimeOnly(fld.ToString());
}
@@ -442,15 +406,11 @@ public DateTime GetTimeOnly(int tag)
///
public bool GetBoolean(int tag)
{
- if (!_fields.TryGetValue(tag, out IField fld))
- {
+ if (!_fields.TryGetValue(tag, out IField? fld))
throw new FieldNotFoundException(tag);
- }
if (fld is FieldBase boolField)
- {
return boolField.Obj;
- }
return BoolConverter.Convert(fld.ToString());
}
@@ -463,10 +423,8 @@ public bool GetBoolean(int tag)
///
public string GetString(int tag)
{
- if (!_fields.TryGetValue(tag, out IField fld))
- {
+ if (!_fields.TryGetValue(tag, out IField? fld))
throw new FieldNotFoundException(tag);
- }
return fld.ToString();
}
@@ -479,15 +437,11 @@ public string GetString(int tag)
///
public char GetChar(int tag)
{
- if (!_fields.TryGetValue(tag, out IField fld))
- {
+ if (!_fields.TryGetValue(tag, out IField? fld))
throw new FieldNotFoundException(tag);
- }
if (fld is FieldBase charField)
- {
return charField.Obj;
- }
return CharConverter.Convert(fld.ToString());
}
@@ -500,15 +454,11 @@ public char GetChar(int tag)
///
public decimal GetDecimal(int tag)
{
- if (!_fields.TryGetValue(tag, out IField fld))
- {
+ if (!_fields.TryGetValue(tag, out IField? fld))
throw new FieldNotFoundException(tag);
- }
if (fld is FieldBase decimalField)
- {
return decimalField.Obj;
- }
return DecimalConverter.Convert(fld.ToString());
}
@@ -569,19 +519,19 @@ public virtual void Clear()
/// true if no fields or groups have been set
public bool IsEmpty()
{
- return ((_fields.Count == 0) && (_groups.Count == 0));
+ return (_fields.Count == 0) && (_groups.Count == 0);
}
public int CalculateTotal()
{
int total = 0;
- foreach (Fields.IField field in _fields.Values)
+ foreach (IField field in _fields.Values)
{
if (field.Tag != Fields.Tags.CheckSum)
total += field.getTotal();
}
- foreach (Fields.IField field in this.RepeatedTags)
+ foreach (IField field in this.RepeatedTags)
{
if (field.Tag != Fields.Tags.CheckSum)
total += field.getTotal();
@@ -598,7 +548,7 @@ public int CalculateTotal()
public int CalculateLength()
{
int total = 0;
- foreach (Fields.IField field in _fields.Values)
+ foreach (IField field in _fields.Values)
{
if (field != null
&& field.Tag != Tags.BeginString
@@ -609,7 +559,7 @@ public int CalculateLength()
}
}
- foreach (Fields.IField field in this.RepeatedTags)
+ foreach (IField field in this.RepeatedTags)
{
if (field != null
&& field.Tag != Tags.BeginString
@@ -631,10 +581,7 @@ public int CalculateLength()
public virtual string CalculateString()
{
- if( FieldOrder != null )
- return CalculateString(new StringBuilder(), FieldOrder);
- else
- return CalculateString(new StringBuilder(), new int[0]);
+ return CalculateString(new StringBuilder(), FieldOrder);
}
public virtual string CalculateString(StringBuilder sb, int[] preFields)
@@ -655,7 +602,7 @@ public virtual string CalculateString(StringBuilder sb, int[] preFields)
}
}
- foreach (Fields.IField field in _fields.Values)
+ foreach (IField field in _fields.Values)
{
if (groupCounterTags.Contains(field.Tag))
continue;
@@ -689,16 +636,8 @@ public virtual string CalculateString(StringBuilder sb, int[] preFields)
///
/// the counter tag of the group
///
- public int GroupCount(int fieldNo)
- {
- if(_groups.ContainsKey(fieldNo))
- {
- return _groups[fieldNo].Count;
- }
- else
- {
- return 0;
- }
+ public int GroupCount(int fieldNo) {
+ return _groups.ContainsKey(fieldNo) ? _groups[fieldNo].Count : 0;
}
///
@@ -711,19 +650,6 @@ public List GetGroupTags()
return new List(_groups.Keys);
}
- #region Private Members
- private SortedDictionary _fields; /// FIXME sorted dict is a hack to get quasi-correct field order
- private Dictionary> _groups;
- protected int[] _fieldOrder;
- #endregion
-
- #region Properties
- ///
- /// Used for validation. Only set during Message parsing.
- ///
- public List RepeatedTags { get; private set; }
- #endregion
-
#region IEnumerable> Members
public IEnumerator> GetEnumerator()
diff --git a/QuickFIXn/Message/FieldNotFoundException.cs b/QuickFIXn/Message/FieldNotFoundException.cs
index f8b81f1d9..da8f86c0a 100644
--- a/QuickFIXn/Message/FieldNotFoundException.cs
+++ b/QuickFIXn/Message/FieldNotFoundException.cs
@@ -1,7 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+#nullable enable
+using System;
namespace QuickFix
{
@@ -16,17 +14,21 @@ public class FieldNotFoundException : ApplicationException
public FieldNotFoundException() { }
public FieldNotFoundException(int tag)
- : base("field not found for tag: " + tag.ToString()) { this.Field = tag; }
+ : base($"field not found for tag: {tag}")
+ { Field = tag; }
public FieldNotFoundException(string message)
- : base(message) { Field = -1; }
+ : base(message)
+ { Field = -1; }
public FieldNotFoundException(string message, System.Exception inner)
- : base(message, inner) { Field = -1; }
+ : base(message, inner)
+ { Field = -1; }
protected FieldNotFoundException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
- : base(info, context) { }
+ : base(info, context)
+ { }
}
}
diff --git a/QuickFIXn/Message/Group.cs b/QuickFIXn/Message/Group.cs
index 9557d1718..16e71d351 100644
--- a/QuickFIXn/Message/Group.cs
+++ b/QuickFIXn/Message/Group.cs
@@ -1,8 +1,6 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
+#nullable enable
+using System;
using System.Text;
-using QuickFix.Fields;
namespace QuickFix
{
@@ -14,24 +12,25 @@ public class Group : FieldMap
///
/// Create a group with the specified count and delimiter fields.
///
- /// tag of the counter field
+ /// tag of the counter field
/// delimiter field's tag (first field in the group)
- public Group(int field, int delim)
+ public Group(int counterField, int delim)
+ :base(fieldOrd: new[] { delim })
{
- Field = field;
+ CounterField = counterField;
Delim = delim;
}
///
/// Create a group with the specified count and delimiter fields and field ordering.
///
- /// tag of the counter field
+ /// tag of the counter field
/// delimiter field's tag (first field in the group)
/// the group's member tags in order
- public Group(int field, int delim, int[] fieldOrd)
+ public Group(int counterField, int delim, int[] fieldOrd)
:base(fieldOrd)
{
- Field = field;
+ CounterField = counterField;
Delim = delim;
}
@@ -42,11 +41,11 @@ public Group(int field, int delim, int[] fieldOrd)
public Group(Group src)
:base(src)
{
- Field = src.Field;
+ CounterField = src.CounterField;
Delim = src.Delim;
}
- virtual public Group Clone()
+ public virtual Group Clone()
{
return new Group(this);
}
@@ -54,37 +53,23 @@ virtual public Group Clone()
///
/// Tag of the group's counter field
///
- public int Field
- {
- get { return _field; }
- private set { _field = value; }
- }
+ public int CounterField { get; }
+
+ [Obsolete("Use CounterField instead")]
+ public int Field => CounterField;
///
/// Tag of the group's delimiter field (first field in the group)
///
- public int Delim
- {
- get { return _delim; }
- private set { _delim = value; }
- }
+ public int Delim { get; }
- public override string CalculateString()
- {
- if (_fieldOrder == null)
- return base.CalculateString(new StringBuilder(), new int[] { _delim });
- else
- return base.CalculateString(new StringBuilder(), _fieldOrder); // 802 shouldn't be in _fieldOrder
+ public override string CalculateString() {
+ return base.CalculateString(new StringBuilder(), FieldOrder ?? new[] { Delim });
}
public override string ToString()
{
return CalculateString();
}
-
- #region Private Members
- private int _field;
- private int _delim;
- #endregion
}
}
diff --git a/QuickFIXn/Message/Header.cs b/QuickFIXn/Message/Header.cs
new file mode 100644
index 000000000..ebfe308fc
--- /dev/null
+++ b/QuickFIXn/Message/Header.cs
@@ -0,0 +1,26 @@
+#nullable enable
+using System;
+using System.Text;
+using QuickFix.Fields;
+
+namespace QuickFix {
+ public class Header : FieldMap {
+ public int[] HEADER_FIELD_ORDER = { Tags.BeginString, Tags.BodyLength, Tags.MsgType };
+
+ public Header()
+ : base() {
+ }
+
+ public Header(Header src)
+ : base(src) {
+ }
+
+ public override string CalculateString() {
+ return base.CalculateString(new StringBuilder(), HEADER_FIELD_ORDER);
+ }
+
+ public override string CalculateString(StringBuilder sb, int[] preFields) {
+ return base.CalculateString(sb, HEADER_FIELD_ORDER);
+ }
+ }
+}
diff --git a/QuickFIXn/Message/Message.cs b/QuickFIXn/Message/Message.cs
index ed6ac8e3c..5bfc60360 100644
--- a/QuickFIXn/Message/Message.cs
+++ b/QuickFIXn/Message/Message.cs
@@ -1,121 +1,70 @@
-using System;
+#nullable enable
+using System;
using System.Text;
using QuickFix.Fields;
using System.Text.RegularExpressions;
using System.Text.Json;
using System.Collections.Generic;
+using QuickFix.DataDictionary;
+using DD = QuickFix.DataDictionary.DataDictionary;
namespace QuickFix
{
- public class Header : FieldMap
- {
- public int[] HEADER_FIELD_ORDER = { Tags.BeginString, Tags.BodyLength, Tags.MsgType };
-
- public Header()
- : base()
- { }
-
- public Header(Header src)
- : base(src)
- { }
-
- public override string CalculateString()
- {
- return base.CalculateString(new StringBuilder(), HEADER_FIELD_ORDER);
- }
-
- public override string CalculateString(StringBuilder sb, int[] preFields)
- {
- return base.CalculateString(sb, HEADER_FIELD_ORDER);
- }
- }
-
- public class Trailer : FieldMap
- {
- public int[] TRAILER_FIELD_ORDER = { Tags.SignatureLength, Tags.Signature, Tags.CheckSum };
-
- public Trailer()
- : base()
- { }
-
- public Trailer(Trailer src)
- : base(src)
- { }
-
- public override string CalculateString()
- {
- return base.CalculateString(new StringBuilder(), TRAILER_FIELD_ORDER);
- }
-
- public override string CalculateString(StringBuilder sb, int[] preFields)
- {
- return base.CalculateString(sb, TRAILER_FIELD_ORDER);
- }
- }
-
///
/// Represents a FIX message
///
public class Message : FieldMap
{
- public const string SOH = "\u0001";
- private int field_ = 0;
- private bool validStructure_;
+ public const char SOH = '\u0001';
- #region Properties
-
- public Header Header { get; private set; }
- public Trailer Trailer { get; private set; }
- public DataDictionary.DataDictionary ApplicationDataDictionary { get; private set; }
+ ///
+ /// If message is invalid, then this is set to the tag that caused it
+ ///
+ private int _invalidField = 0;
- #endregion
+ private bool _isValid = false;
- #region Constructors
+ public Header Header { get; }
+ public Trailer Trailer { get; }
public Message()
{
- this.Header = new Header();
- this.Trailer = new Trailer();
- this.validStructure_ = true;
+ Header = new Header();
+ Trailer = new Trailer();
+ _isValid = true;
}
- public Message(string msgstr)
- : this(msgstr, true)
+ public Message(
+ string msgStr,
+ bool validate = true)
+ : this(msgStr, null, null, validate)
{ }
- public Message(string msgstr, bool validate)
- : this(msgstr, null, null, validate)
- { }
-
- public Message(string msgstr, DataDictionary.DataDictionary dataDictionary, bool validate)
- : this()
- {
- this.ApplicationDataDictionary = dataDictionary;
- FromString(msgstr, validate, dataDictionary, dataDictionary, null);
- }
-
- public Message(string msgstr, DataDictionary.DataDictionary sessionDataDictionary, DataDictionary.DataDictionary appDD, bool validate)
+ ///
+ ///
+ ///
+ /// (if FIX4, transportDict and appDict should be the same)
+ /// (if FIX4, transportDict and appDict should be the same)
+ ///
+ public Message(string msgstr, DD? transportDict, DD? appDict, bool validate)
: this()
{
- this.ApplicationDataDictionary = appDD;
- FromStringHeader(msgstr);
- if(IsAdmin())
- FromString(msgstr, validate, sessionDataDictionary, sessionDataDictionary, null);
+ PopulateHeaderFromMessageString(msgstr);
+ if (IsAdmin())
+ FromString(msgstr, validate, transportDict, transportDict, null, false);
else
- FromString(msgstr, validate, sessionDataDictionary, appDD, null);
+ FromString(msgstr, validate, transportDict, appDict, null, false);
}
public Message(Message src)
: base(src)
{
- this.Header = new Header(src.Header);
- this.Trailer = new Trailer(src.Trailer);
- this.validStructure_ = src.validStructure_;
- this.field_= src.field_;
+ Header = new Header(src.Header);
+ Trailer = new Trailer(src.Trailer);
+ _isValid = src._isValid;
+ _invalidField = src._invalidField;
}
- #endregion
-
#region Static Methods
public static bool IsAdminMsgType(string msgType)
@@ -134,7 +83,7 @@ public static MsgType IdentifyType(string fixstring)
return new MsgType(GetMsgType(fixstring));
}
- public static StringField ExtractField(string msgstr, ref int pos, DataDictionary.DataDictionary sessionDD, DataDictionary.DataDictionary appDD)
+ public static StringField ExtractField(string msgstr, ref int pos)
{
try
{
@@ -144,56 +93,27 @@ public static StringField ExtractField(string msgstr, ref int pos, DataDictionar
int fieldvalend = msgstr.IndexOf((char)1, pos);
StringField field = new StringField(tag, msgstr.Substring(pos, fieldvalend - pos));
- /*
- TODO data dict stuff
- if (((null != sessionDD) && sessionDD.IsDataField(field.Tag)) || ((null != appDD) && appDD.IsDataField(field.Tag)))
- {
- string fieldLength = "";
- // Assume length field is 1 less
- int lenField = field.Tag - 1;
- // Special case for Signature which violates above assumption
- if (Tags.Signature.Equals(field.Tag))
- lenField = Tags.SignatureLength;
-
- if ((null != group) && group.isSetField(lenField))
- {
- fieldLength = group.GetField(lenField);
- soh = equalSign + 1 + atol(fieldLength.c_str());
- }
- else if (isSetField(lenField))
- {
- fieldLength = getField(lenField);
- soh = equalSign + 1 + atol(fieldLength.c_str());
- }
- }
- */
-
pos = fieldvalend + 1;
return field;
}
- catch (System.ArgumentOutOfRangeException e)
+ catch (ArgumentOutOfRangeException e)
{
throw new MessageParseError("Error at position (" + pos + ") while parsing msg (" + msgstr + ")", e);
}
- catch (System.OverflowException e)
+ catch (OverflowException e)
{
throw new MessageParseError("Error at position (" + pos + ") while parsing msg (" + msgstr + ")", e);
}
- catch (System.FormatException e)
+ catch (FormatException e)
{
throw new MessageParseError("Error at position (" + pos + ") while parsing msg (" + msgstr + ")", e);
}
}
- public static StringField ExtractField(string msgstr, ref int pos)
- {
- return ExtractField(msgstr, ref pos, null, null);
- }
-
public static string ExtractBeginString(string msgstr)
{
int i = 0;
- return ExtractField(msgstr, ref i, null, null).Obj;
+ return ExtractField(msgstr, ref i).Obj;
}
public static bool IsHeaderField(int tag)
@@ -231,11 +151,11 @@ public static bool IsHeaderField(int tag)
return false;
}
}
- public static bool IsHeaderField(int tag, DataDictionary.DataDictionary dd)
+ public static bool IsHeaderField(int tag, DD? dd)
{
if (IsHeaderField(tag))
return true;
- if (null != dd)
+ if (dd is not null)
return dd.IsHeaderField(tag);
return false;
}
@@ -252,16 +172,16 @@ public static bool IsTrailerField(int tag)
return false;
}
}
- public static bool IsTrailerField(int tag, DataDictionary.DataDictionary dd)
+ public static bool IsTrailerField(int tag, DD? dd)
{
if (IsTrailerField(tag))
return true;
- if (null != dd)
+ if (dd is not null)
return dd.IsTrailerField(tag);
return false;
}
- public static string GetFieldOrDefault(FieldMap fields, int tag, string defaultValue)
+ private static string GetFieldOrDefault(FieldMap fields, int tag, string defaultValue)
{
if (!fields.IsSetField(tag))
return defaultValue;
@@ -276,28 +196,23 @@ public static string GetFieldOrDefault(FieldMap fields, int tag, string defaultV
}
}
- public static SessionID GetReverseSessionID(Message msg)
+ private static SessionID GetReverseSessionId(Message msg)
{
return new SessionID(
- GetFieldOrDefault(msg.Header, Tags.BeginString, null),
- GetFieldOrDefault(msg.Header, Tags.TargetCompID, null),
+ GetFieldOrDefault(msg.Header, Tags.BeginString, SessionID.NOT_SET),
+ GetFieldOrDefault(msg.Header, Tags.TargetCompID, SessionID.NOT_SET),
GetFieldOrDefault(msg.Header, Tags.TargetSubID, SessionID.NOT_SET),
GetFieldOrDefault(msg.Header, Tags.TargetLocationID, SessionID.NOT_SET),
- GetFieldOrDefault(msg.Header, Tags.SenderCompID, null),
+ GetFieldOrDefault(msg.Header, Tags.SenderCompID, SessionID.NOT_SET),
GetFieldOrDefault(msg.Header, Tags.SenderSubID, SessionID.NOT_SET),
GetFieldOrDefault(msg.Header, Tags.SenderLocationID, SessionID.NOT_SET)
);
}
- ///
- /// FIXME works, but implementation is shady
- ///
- ///
- ///
- public static SessionID GetReverseSessionID(string msg)
+ public static SessionID GetReverseSessionId(string msg)
{
- Message FIXME = new Message(msg);
- return GetReverseSessionID(FIXME);
+ Message m = new Message(msg);
+ return GetReverseSessionId(m);
}
///
@@ -308,7 +223,7 @@ public static SessionID GetReverseSessionID(string msg)
/// if 35 tag is missing or malformed
public static string GetMsgType(string fixstring)
{
- Match match = Regex.Match(fixstring, Message.SOH + "35=([^" + Message.SOH + "]*)" + Message.SOH);
+ Match match = Regex.Match(fixstring, SOH + "35=([^" + SOH + "]*)" + SOH);
if (match.Success)
return match.Groups[1].Value;
@@ -336,59 +251,38 @@ public static ApplVerID GetApplVerID(string beginString)
case FixValues.BeginString.FIX50SP2:
return new ApplVerID(ApplVerID.FIX50SP2);
default:
- throw new System.ArgumentException(String.Format("ApplVerID for {0} not supported", beginString));
+ throw new ArgumentException($"ApplVerID for {beginString} not supported");
}
}
#endregion
- public bool FromStringHeader(string msgstr)
+ public override void Clear()
+ {
+ _invalidField = 0;
+ Header.Clear();
+ base.Clear();
+ Trailer.Clear();
+ }
+
+ private void PopulateHeaderFromMessageString(string msgstr)
{
Clear();
-
+
int pos = 0;
int count = 0;
while(pos < msgstr.Length)
{
StringField f = ExtractField(msgstr, ref pos);
-
- if((count < 3) && (Header.HEADER_FIELD_ORDER[count++] != f.Tag))
- return false;
+
+ if (count < 3 && Header.HEADER_FIELD_ORDER[count++] != f.Tag)
+ return;
if(IsHeaderField(f.Tag))
- this.Header.SetField(f, false);
+ Header.SetField(f, false);
else
break;
}
- return true;
- }
-
- ///
- /// Creates a Message from a FIX string
- ///
- ///
- ///
- ///
- ///
- public void FromString(string msgstr, bool validate, DataDictionary.DataDictionary sessionDD, DataDictionary.DataDictionary appDD)
- {
- this.ApplicationDataDictionary = appDD;
- FromString(msgstr, validate, sessionDD, appDD, null);
- }
-
- ///
- /// Create a Message from a FIX string
- ///
- ///
- ///
- ///
- ///
- /// If null, any groups will be constructed as generic Group objects
- public void FromString(string msgstr, bool validate,
- DataDictionary.DataDictionary sessionDD, DataDictionary.DataDictionary appDD, IMessageFactory msgFactory)
- {
- this.ApplicationDataDictionary = appDD;
- FromString(msgstr, validate, sessionDD, appDD, msgFactory, false);
}
///
@@ -396,90 +290,91 @@ public void FromString(string msgstr, bool validate,
///
///
///
- ///
- ///
+ /// (if FIX4, transportDict and appDict should be the same)
+ /// (if FIX4, transportDict and appDict will be the same)
/// If null, any groups will be constructed as generic Group objects
/// (default false) if true, ignores all non-header non-trailer fields.
/// Intended for callers that only need rejection-related information from the header.
///
- public void FromString(string msgstr, bool validate,
- DataDictionary.DataDictionary sessionDD, DataDictionary.DataDictionary appDD, IMessageFactory msgFactory,
- bool ignoreBody)
+ public void FromString(
+ string msgstr,
+ bool validate,
+ DD? transportDict,
+ DD? appDict,
+ IMessageFactory? msgFactory = null,
+ bool ignoreBody = false)
{
- this.ApplicationDataDictionary = appDD;
Clear();
- string msgType = "";
bool expectingHeader = true;
bool expectingBody = true;
int count = 0;
int pos = 0;
- DataDictionary.IFieldMapSpec msgMap = null;
+ IFieldMapSpec? msgMap = null;
while (pos < msgstr.Length)
{
- StringField f = ExtractField(msgstr, ref pos, sessionDD, appDD);
+ StringField f = ExtractField(msgstr, ref pos);
- if (validate && (count < 3) && (Header.HEADER_FIELD_ORDER[count++] != f.Tag))
+ if (validate && count < 3 && Header.HEADER_FIELD_ORDER[count++] != f.Tag)
throw new InvalidMessage("Header fields out of order");
- if (IsHeaderField(f.Tag, sessionDD))
+ if (IsHeaderField(f.Tag, transportDict))
{
if (!expectingHeader)
{
- if (0 == field_)
- field_ = f.Tag;
- validStructure_ = false;
+ if (0 == _invalidField)
+ _invalidField = f.Tag;
+ _isValid = false;
}
if (Tags.MsgType.Equals(f.Tag))
{
- msgType = f.Obj;
- if (appDD != null)
+ string msgType = f.Obj;
+ if (appDict is not null)
{
- msgMap = appDD.GetMapForMessage(msgType);
+ msgMap = appDict.GetMapForMessage(msgType);
}
- }
+ }
- if (!this.Header.SetField(f, false))
- this.Header.RepeatedTags.Add(f);
+ if (!Header.SetField(f, false))
+ Header.RepeatedTags.Add(f);
- if ((null != sessionDD) && sessionDD.Header.IsGroup(f.Tag))
+ if (transportDict is not null && transportDict.Header.IsGroup(f.Tag))
{
- pos = SetGroup(f, msgstr, pos, this.Header, sessionDD.Header.GetGroupSpec(f.Tag), sessionDD, appDD, msgFactory);
+ pos = SetGroup(f, msgstr, pos, Header, transportDict.Header.GetGroupSpec(f.Tag), msgFactory);
}
}
- else if (IsTrailerField(f.Tag, sessionDD))
+ else if (IsTrailerField(f.Tag, transportDict))
{
expectingHeader = false;
expectingBody = false;
- if (!this.Trailer.SetField(f, false))
- this.Trailer.RepeatedTags.Add(f);
+ if (!Trailer.SetField(f, false))
+ Trailer.RepeatedTags.Add(f);
- if ((null != sessionDD) && sessionDD.Trailer.IsGroup(f.Tag))
+ if (transportDict is not null && transportDict.Trailer.IsGroup(f.Tag))
{
- pos = SetGroup(f, msgstr, pos, this.Trailer, sessionDD.Trailer.GetGroup(f.Tag), sessionDD, appDD, msgFactory);
+ pos = SetGroup(f, msgstr, pos, Trailer, transportDict.Trailer.GetGroup(f.Tag), msgFactory);
}
}
else if (ignoreBody==false)
{
if (!expectingBody)
{
- if (0 == field_)
- field_ = f.Tag;
- validStructure_ = false;
+ if (0 == _invalidField)
+ _invalidField = f.Tag;
+ _isValid = false;
}
expectingHeader = false;
if (!SetField(f, false))
{
- this.RepeatedTags.Add(f);
+ RepeatedTags.Add(f);
}
-
- if((null != msgMap) && (msgMap.IsGroup(f.Tag)))
+ if(msgMap is not null && msgMap.IsGroup(f.Tag))
{
- pos = SetGroup(f, msgstr, pos, this, msgMap.GetGroupSpec(f.Tag), sessionDD, appDD, msgFactory);
+ pos = SetGroup(f, msgstr, pos, this, msgMap.GetGroupSpec(f.Tag), msgFactory);
}
}
}
@@ -496,26 +391,33 @@ public void FromString(string msgstr, bool validate,
///
///
///
- ///
- ///
+ ///
+ ///
/// If null, any groups will be constructed as generic Group objects
- public void FromJson(string json, bool validate, DataDictionary.DataDictionary sessionDD, DataDictionary.DataDictionary appDD, IMessageFactory msgFactory)
+ public void FromJson(string json, bool validate,
+ DD transportDict,
+ DD appDict,
+ IMessageFactory? msgFactory)
{
- this.ApplicationDataDictionary = appDD;
Clear();
- using (JsonDocument document = JsonDocument.Parse(json))
- {
- string beginString = document.RootElement.GetProperty("Header").GetProperty("BeginString").GetString();
- string msgType = document.RootElement.GetProperty("Header").GetProperty("MsgType").GetString();
- DataDictionary.IFieldMapSpec msgMap = appDD.GetMapForMessage(msgType);
- FromJson(document.RootElement.GetProperty("Header"), beginString, msgType, msgMap, msgFactory, sessionDD, this.Header);
- FromJson(document.RootElement.GetProperty("Body"), beginString, msgType, msgMap, msgFactory, appDD, this);
- FromJson(document.RootElement.GetProperty("Trailer"), beginString, msgType, msgMap, msgFactory, sessionDD, this.Trailer);
+ using (JsonDocument document = JsonDocument.Parse(json)) {
+ string? beginString = document.RootElement.GetProperty("Header").GetProperty("BeginString").GetString();
+ string? msgType = document.RootElement.GetProperty("Header").GetProperty("MsgType").GetString();
+
+ if (beginString is null || msgType is null) {
+ throw new ArgumentException(
+ $"JSON message has invalid/missing beginString ({beginString}) and/or msgType ({msgType})");
+ }
+
+ IFieldMapSpec msgMap = appDict.GetMapForMessage(msgType);
+ FromJson(document.RootElement.GetProperty("Header"), beginString, msgType, msgMap, msgFactory, transportDict, Header);
+ FromJson(document.RootElement.GetProperty("Body"), beginString, msgType, msgMap, msgFactory, appDict, this);
+ FromJson(document.RootElement.GetProperty("Trailer"), beginString, msgType, msgMap, msgFactory, transportDict, Trailer);
}
- this.Header.SetField(new BodyLength(BodyLength()), true);
- this.Trailer.SetField(new CheckSum(Fields.Converters.CheckSumConverter.Convert(CheckSum())), true);
+ Header.SetField(new BodyLength(BodyLength()), true);
+ Trailer.SetField(new CheckSum(Fields.Converters.CheckSumConverter.Convert(CheckSum())), true);
if (validate)
{
@@ -523,19 +425,27 @@ public void FromJson(string json, bool validate, DataDictionary.DataDictionary s
}
}
- protected void FromJson(JsonElement jsonElement, string beginString, string msgType, DataDictionary.IFieldMapSpec msgMap, IMessageFactory msgFactory, DataDictionary.DataDictionary dataDict, FieldMap fieldMap)
+ protected void FromJson(JsonElement jsonElement,
+ string beginString,
+ string msgType,
+ IFieldMapSpec msgMap,
+ IMessageFactory? msgFactory,
+ DD dataDict,
+ FieldMap fieldMap)
{
foreach (JsonProperty field in jsonElement.EnumerateObject())
{
- DataDictionary.DDField ddField;
- if (dataDict.FieldsByName.TryGetValue(field.Name.ToString(), out ddField))
+ if (dataDict.FieldsByName.TryGetValue(field.Name, out DDField? ddField))
{
- if ((null != msgMap) && (msgMap.IsGroup(ddField.Tag)) && (JsonValueKind.Array == field.Value.ValueKind))
+ if (msgMap is not null && msgMap.IsGroup(ddField.Tag) && JsonValueKind.Array == field.Value.ValueKind)
{
foreach (JsonElement jsonGrp in field.Value.EnumerateArray())
{
- Group grp = msgFactory.Create(beginString, msgType, ddField.Tag);
- FromJson(jsonGrp, beginString, msgType, msgMap.GetGroupSpec(ddField.Tag), msgFactory, dataDict, grp);
+ IGroupSpec grpSpec = msgMap.GetGroupSpec(ddField.Tag);
+
+ Group grp = msgFactory?.Create(beginString, msgType, ddField.Tag)
+ ?? new Group(ddField.Tag, grpSpec.Delim);
+ FromJson(jsonGrp, beginString, msgType, grpSpec, msgFactory, dataDict, grp);
fieldMap.AddGroup(grp);
}
}
@@ -548,7 +458,7 @@ protected void FromJson(JsonElement jsonElement, string beginString, string msgT
else
{
// this may be a custom tag given by number instead of name
- if (Int32.TryParse(field.Name.ToString(), out int customTagNumber))
+ if (int.TryParse(field.Name, out int customTagNumber))
{
fieldMap.SetField(new StringField(customTagNumber, field.Value.ToString()));
}
@@ -563,59 +473,52 @@ protected void FromJson(JsonElement jsonElement, string beginString, string msgT
/// full message string
/// starting character position of group
/// full message as FieldMap
- /// group definition structure from dd
- ///
- ///
+ /// group definition structure from dd
/// if null, then this method will use the generic Group class constructor
///
protected int SetGroup(
- StringField grpNoFld, string msgstr, int pos, FieldMap fieldMap, DataDictionary.IGroupSpec groupDD,
- DataDictionary.DataDictionary sessionDataDictionary, DataDictionary.DataDictionary appDD, IMessageFactory msgFactory)
+ StringField grpNoFld, string msgstr, int pos, FieldMap fieldMap, IGroupSpec groupSpec,
+ IMessageFactory? msgFactory)
{
- int grpEntryDelimiterTag = groupDD.Delim;
+ int grpEntryDelimiterTag = groupSpec.Delim;
int grpPos = pos;
- Group grp = null; // the group entry being constructed
+ Group? grp = null; // the group entry being constructed
while (pos < msgstr.Length)
{
grpPos = pos;
- StringField f = ExtractField(msgstr, ref pos, sessionDataDictionary, appDD);
+ StringField f = ExtractField(msgstr, ref pos);
if (f.Tag == grpEntryDelimiterTag)
{
// This is the start of a group entry.
- if (grp != null)
+ if (grp is not null)
{
// We were already building an entry, so the delimiter means it's done.
fieldMap.AddGroup(grp, false);
- grp = null; // prepare for new Group
}
// Create a new group!
- if (msgFactory != null)
- grp = msgFactory.Create(Message.ExtractBeginString(msgstr), Message.GetMsgType(msgstr), grpNoFld.Tag);
-
- //If above failed (shouldn't ever happen), just use a generic Group.
- if (grp == null)
- grp = new Group(grpNoFld.Tag, grpEntryDelimiterTag);
+ grp = msgFactory?.Create(ExtractBeginString(msgstr), GetMsgType(msgstr), grpNoFld.Tag)
+ ?? new Group(grpNoFld.Tag, grpEntryDelimiterTag);
}
- else if (!groupDD.IsField(f.Tag))
+ else if (!groupSpec.IsField(f.Tag))
{
// This field is not in the group, thus the repeating group is done.
- if (grp != null)
+ if (grp is not null)
{
fieldMap.AddGroup(grp, false);
}
return grpPos;
}
- else if(groupDD.IsField(f.Tag) && grp != null && grp.IsSetField(f.Tag))
+ else if(groupSpec.IsField(f.Tag) && grp is not null && grp.IsSetField(f.Tag))
{
// Tag is appearing for the second time within a group element.
// Presumably the sender didn't set the delimiter (or their DD has a different delimiter).
throw new RepeatedTagWithoutGroupDelimiterTagException(grpNoFld.Tag, f.Tag);
}
- if (grp == null)
+ if (grp is null)
{
// This means we got into the group's fields without finding a delimiter tag.
throw new GroupDelimiterTagException(grpNoFld.Tag, grpEntryDelimiterTag);
@@ -623,33 +526,37 @@ protected int SetGroup(
// f is just a field in our group entry. Add it and iterate again.
grp.SetField(f);
- if(groupDD.IsGroup(f.Tag))
+ if(groupSpec.IsGroup(f.Tag))
{
// f is a counter for a nested group. Recurse!
- pos = SetGroup(f, msgstr, pos, grp, groupDD.GetGroupSpec(f.Tag), sessionDataDictionary, appDD, msgFactory);
+ pos = SetGroup(f, msgstr, pos, grp, groupSpec.GetGroupSpec(f.Tag), msgFactory);
}
}
return grpPos;
}
- public bool HasValidStructure(out int field)
- {
- field = field_;
- return validStructure_;
+ ///
+ /// Check if this message was deemed valid.
+ ///
+ /// If invalid, then this is set to the field that is the problem
+ ///
+ public bool HasValidStructure(out int problemField) {
+ problemField = _isValid ? 0 : _invalidField;
+ return _isValid;
}
public void Validate()
{
try
{
- int receivedBodyLength = this.Header.GetInt(Tags.BodyLength);
+ int receivedBodyLength = Header.GetInt(Tags.BodyLength);
if (BodyLength() != receivedBodyLength)
- throw new InvalidMessage("Expected BodyLength=" + BodyLength() + ", Received BodyLength=" + receivedBodyLength + ", Message.SeqNum=" + this.Header.GetInt(Tags.MsgSeqNum));
+ throw new InvalidMessage("Expected BodyLength=" + BodyLength() + ", Received BodyLength=" + receivedBodyLength + ", Message.SeqNum=" + Header.GetInt(Tags.MsgSeqNum));
- int receivedCheckSum = this.Trailer.GetInt(Tags.CheckSum);
+ int receivedCheckSum = Trailer.GetInt(Tags.CheckSum);
if (CheckSum() != receivedCheckSum)
- throw new InvalidMessage("Expected CheckSum=" + CheckSum() + ", Received CheckSum=" + receivedCheckSum + ", Message.SeqNum=" + this.Header.GetInt(Tags.MsgSeqNum));
+ throw new InvalidMessage("Expected CheckSum=" + CheckSum() + ", Received CheckSum=" + receivedCheckSum + ", Message.SeqNum=" + Header.GetInt(Tags.MsgSeqNum));
}
catch (FieldNotFoundException e)
{
@@ -664,189 +571,182 @@ public void Validate()
public void ReverseRoute(Header header)
{
// required routing tags
- this.Header.RemoveField(Tags.BeginString);
- this.Header.RemoveField(Tags.SenderCompID);
- this.Header.RemoveField(Tags.SenderSubID);
- this.Header.RemoveField(Tags.SenderLocationID);
- this.Header.RemoveField(Tags.TargetCompID);
- this.Header.RemoveField(Tags.TargetSubID);
- this.Header.RemoveField(Tags.TargetLocationID);
+ Header.RemoveField(Tags.BeginString);
+ Header.RemoveField(Tags.SenderCompID);
+ Header.RemoveField(Tags.SenderSubID);
+ Header.RemoveField(Tags.SenderLocationID);
+ Header.RemoveField(Tags.TargetCompID);
+ Header.RemoveField(Tags.TargetSubID);
+ Header.RemoveField(Tags.TargetLocationID);
if (header.IsSetField(Tags.BeginString))
{
string beginString = header.GetString(Tags.BeginString);
if (beginString.Length > 0)
- this.Header.SetField(new BeginString(beginString));
+ Header.SetField(new BeginString(beginString));
- this.Header.RemoveField(Tags.OnBehalfOfLocationID);
- this.Header.RemoveField(Tags.DeliverToLocationID);
+ Header.RemoveField(Tags.OnBehalfOfLocationID);
+ Header.RemoveField(Tags.DeliverToLocationID);
if (string.CompareOrdinal(beginString, "FIX.4.1") >= 0)
{
if (header.IsSetField(Tags.OnBehalfOfLocationID))
{
- string onBehalfOfLocationID = header.GetString(Tags.OnBehalfOfLocationID);
- if (onBehalfOfLocationID.Length > 0)
- this.Header.SetField(new DeliverToLocationID(onBehalfOfLocationID));
+ string onBehalfOfLocationId = header.GetString(Tags.OnBehalfOfLocationID);
+ if (onBehalfOfLocationId.Length > 0)
+ Header.SetField(new DeliverToLocationID(onBehalfOfLocationId));
}
if (header.IsSetField(Tags.DeliverToLocationID))
{
- string deliverToLocationID = header.GetString(Tags.DeliverToLocationID);
- if (deliverToLocationID.Length > 0)
- this.Header.SetField(new OnBehalfOfLocationID(deliverToLocationID));
+ string deliverToLocationId = header.GetString(Tags.DeliverToLocationID);
+ if (deliverToLocationId.Length > 0)
+ Header.SetField(new OnBehalfOfLocationID(deliverToLocationId));
}
}
}
if (header.IsSetField(Tags.SenderCompID))
{
- SenderCompID senderCompID = new SenderCompID();
- header.GetField(senderCompID);
- if (senderCompID.Obj.Length > 0)
- this.Header.SetField(new TargetCompID(senderCompID.Obj));
+ SenderCompID senderCompId = new SenderCompID();
+ header.GetField(senderCompId);
+ if (senderCompId.Obj.Length > 0)
+ Header.SetField(new TargetCompID(senderCompId.Obj));
}
if (header.IsSetField(Tags.SenderSubID))
{
- SenderSubID senderSubID = new SenderSubID();
- header.GetField(senderSubID);
- if (senderSubID.Obj.Length > 0)
- this.Header.SetField(new TargetSubID(senderSubID.Obj));
+ SenderSubID senderSubId = new SenderSubID();
+ header.GetField(senderSubId);
+ if (senderSubId.Obj.Length > 0)
+ Header.SetField(new TargetSubID(senderSubId.Obj));
}
if (header.IsSetField(Tags.SenderLocationID))
{
- SenderLocationID senderLocationID = new SenderLocationID();
- header.GetField(senderLocationID);
- if (senderLocationID.Obj.Length > 0)
- this.Header.SetField(new TargetLocationID(senderLocationID.Obj));
+ SenderLocationID senderLocationId = new SenderLocationID();
+ header.GetField(senderLocationId);
+ if (senderLocationId.Obj.Length > 0)
+ Header.SetField(new TargetLocationID(senderLocationId.Obj));
}
if (header.IsSetField(Tags.TargetCompID))
{
- TargetCompID targetCompID = new TargetCompID();
- header.GetField(targetCompID);
- if (targetCompID.Obj.Length > 0)
- this.Header.SetField(new SenderCompID(targetCompID.Obj));
+ TargetCompID targetCompId = new TargetCompID();
+ header.GetField(targetCompId);
+ if (targetCompId.Obj.Length > 0)
+ Header.SetField(new SenderCompID(targetCompId.Obj));
}
if (header.IsSetField(Tags.TargetSubID))
{
- TargetSubID targetSubID = new TargetSubID();
- header.GetField(targetSubID);
- if (targetSubID.Obj.Length > 0)
- this.Header.SetField(new SenderSubID(targetSubID.Obj));
+ TargetSubID targetSubId = new TargetSubID();
+ header.GetField(targetSubId);
+ if (targetSubId.Obj.Length > 0)
+ Header.SetField(new SenderSubID(targetSubId.Obj));
}
if (header.IsSetField(Tags.TargetLocationID))
{
- TargetLocationID targetLocationID = new TargetLocationID();
- header.GetField(targetLocationID);
- if (targetLocationID.Obj.Length > 0)
- this.Header.SetField(new SenderLocationID(targetLocationID.Obj));
+ TargetLocationID targetLocationId = new TargetLocationID();
+ header.GetField(targetLocationId);
+ if (targetLocationId.Obj.Length > 0)
+ Header.SetField(new SenderLocationID(targetLocationId.Obj));
}
// optional routing tags
- this.Header.RemoveField(Tags.OnBehalfOfCompID);
- this.Header.RemoveField(Tags.OnBehalfOfSubID);
- this.Header.RemoveField(Tags.DeliverToCompID);
- this.Header.RemoveField(Tags.DeliverToSubID);
+ Header.RemoveField(Tags.OnBehalfOfCompID);
+ Header.RemoveField(Tags.OnBehalfOfSubID);
+ Header.RemoveField(Tags.DeliverToCompID);
+ Header.RemoveField(Tags.DeliverToSubID);
if(header.IsSetField(Tags.OnBehalfOfCompID))
{
- string onBehalfOfCompID = header.GetString(Tags.OnBehalfOfCompID);
- if(onBehalfOfCompID.Length > 0)
- this.Header.SetField(new DeliverToCompID(onBehalfOfCompID));
+ string onBehalfOfCompId = header.GetString(Tags.OnBehalfOfCompID);
+ if(onBehalfOfCompId.Length > 0)
+ Header.SetField(new DeliverToCompID(onBehalfOfCompId));
}
if(header.IsSetField(Tags.OnBehalfOfSubID))
{
- string onBehalfOfSubID = header.GetString( Tags.OnBehalfOfSubID);
- if(onBehalfOfSubID.Length > 0)
- this.Header.SetField(new DeliverToSubID(onBehalfOfSubID));
+ string onBehalfOfSubId = header.GetString( Tags.OnBehalfOfSubID);
+ if(onBehalfOfSubId.Length > 0)
+ Header.SetField(new DeliverToSubID(onBehalfOfSubId));
}
if(header.IsSetField(Tags.DeliverToCompID))
{
- string deliverToCompID = header.GetString(Tags.DeliverToCompID);
- if(deliverToCompID.Length > 0)
- this.Header.SetField(new OnBehalfOfCompID(deliverToCompID));
+ string deliverToCompId = header.GetString(Tags.DeliverToCompID);
+ if(deliverToCompId.Length > 0)
+ Header.SetField(new OnBehalfOfCompID(deliverToCompId));
}
if(header.IsSetField(Tags.DeliverToSubID))
{
- string deliverToSubID = header.GetString(Tags.DeliverToSubID);
- if(deliverToSubID.Length > 0)
- this.Header.SetField(new OnBehalfOfSubID(deliverToSubID));
+ string deliverToSubId = header.GetString(Tags.DeliverToSubID);
+ if(deliverToSubId.Length > 0)
+ Header.SetField(new OnBehalfOfSubID(deliverToSubId));
}
}
public int CheckSum()
{
return (
- (this.Header.CalculateTotal()
+ (Header.CalculateTotal()
+ CalculateTotal()
- + this.Trailer.CalculateTotal()) % 256);
+ + Trailer.CalculateTotal()) % 256);
}
public bool IsAdmin()
{
- return this.Header.IsSetField(Tags.MsgType) && IsAdminMsgType(this.Header.GetString(Tags.MsgType));
+ return Header.IsSetField(Tags.MsgType) && IsAdminMsgType(Header.GetString(Tags.MsgType));
}
public bool IsApp()
{
- return this.Header.IsSetField(Tags.MsgType) && !IsAdminMsgType(this.Header.GetString(Tags.MsgType));
+ return Header.IsSetField(Tags.MsgType) && !IsAdminMsgType(Header.GetString(Tags.MsgType));
}
///
/// FIXME less operator new
///
- ///
- public void SetSessionID(SessionID sessionID)
- {
- this.Header.SetField(new BeginString(sessionID.BeginString));
- this.Header.SetField(new SenderCompID(sessionID.SenderCompID));
- if (SessionID.IsSet(sessionID.SenderSubID))
- this.Header.SetField(new SenderSubID(sessionID.SenderSubID));
- if (SessionID.IsSet(sessionID.SenderLocationID))
- this.Header.SetField(new SenderLocationID(sessionID.SenderLocationID));
- this.Header.SetField(new TargetCompID(sessionID.TargetCompID));
- if (SessionID.IsSet(sessionID.TargetSubID))
- this.Header.SetField(new TargetSubID(sessionID.TargetSubID));
- if (SessionID.IsSet(sessionID.TargetLocationID))
- this.Header.SetField(new TargetLocationID(sessionID.TargetLocationID));
+ ///
+ public void SetSessionID(SessionID sessionId)
+ {
+ Header.SetField(new BeginString(sessionId.BeginString));
+ Header.SetField(new SenderCompID(sessionId.SenderCompID));
+ if (SessionID.IsSet(sessionId.SenderSubID))
+ Header.SetField(new SenderSubID(sessionId.SenderSubID));
+ if (SessionID.IsSet(sessionId.SenderLocationID))
+ Header.SetField(new SenderLocationID(sessionId.SenderLocationID));
+ Header.SetField(new TargetCompID(sessionId.TargetCompID));
+ if (SessionID.IsSet(sessionId.TargetSubID))
+ Header.SetField(new TargetSubID(sessionId.TargetSubID));
+ if (SessionID.IsSet(sessionId.TargetLocationID))
+ Header.SetField(new TargetLocationID(sessionId.TargetLocationID));
}
public SessionID GetSessionID(Message m)
{
- bool senderSubIDSet = m.Header.IsSetField(Tags.SenderSubID);
- bool senderLocationIDSet = m.Header.IsSetField(Tags.SenderLocationID);
- bool targetSubIDSet = m.Header.IsSetField(Tags.TargetSubID);
- bool targetLocationIDSet = m.Header.IsSetField(Tags.TargetLocationID);
+ bool isSetSenderSubId = m.Header.IsSetField(Tags.SenderSubID);
+ bool isSetSenderLocationId = m.Header.IsSetField(Tags.SenderLocationID);
+ bool isSetTargetSubId = m.Header.IsSetField(Tags.TargetSubID);
+ bool isSetTargetLocationId = m.Header.IsSetField(Tags.TargetLocationID);
- if (senderSubIDSet && senderLocationIDSet && targetSubIDSet && targetLocationIDSet)
+ if (isSetSenderSubId && isSetSenderLocationId && isSetTargetSubId && isSetTargetLocationId)
return new SessionID(m.Header.GetString(Tags.BeginString),
m.Header.GetString(Tags.SenderCompID), m.Header.GetString(Tags.SenderSubID), m.Header.GetString(Tags.SenderLocationID),
m.Header.GetString(Tags.TargetCompID), m.Header.GetString(Tags.TargetSubID), m.Header.GetString(Tags.TargetLocationID));
- else if (senderSubIDSet && targetSubIDSet)
+
+ if (isSetSenderSubId && isSetTargetSubId)
return new SessionID(m.Header.GetString(Tags.BeginString),
m.Header.GetString(Tags.SenderCompID), m.Header.GetString(Tags.SenderSubID),
m.Header.GetString(Tags.TargetCompID), m.Header.GetString(Tags.TargetSubID));
- else
- return new SessionID(
- m.Header.GetString(Tags.BeginString),
- m.Header.GetString(Tags.SenderCompID),
- m.Header.GetString(Tags.TargetCompID));
- }
- public override void Clear()
- {
- field_ = 0;
- this.Header.Clear();
- base.Clear();
- this.Trailer.Clear();
+ return new SessionID(
+ m.Header.GetString(Tags.BeginString),
+ m.Header.GetString(Tags.SenderCompID),
+ m.Header.GetString(Tags.TargetCompID));
}
private Object lock_ToString = new Object();
@@ -854,33 +754,32 @@ public override string ToString()
{
lock (lock_ToString)
{
- this.Header.SetField(new BodyLength(BodyLength()), true);
- this.Trailer.SetField(new CheckSum(Fields.Converters.CheckSumConverter.Convert(CheckSum())), true);
+ Header.SetField(new BodyLength(BodyLength()), true);
+ Trailer.SetField(new CheckSum(Fields.Converters.CheckSumConverter.Convert(CheckSum())), true);
- return this.Header.CalculateString() + CalculateString() + this.Trailer.CalculateString();
+ return Header.CalculateString() + CalculateString() + Trailer.CalculateString();
}
}
protected int BodyLength()
{
- return this.Header.CalculateLength() + CalculateLength() + this.Trailer.CalculateLength();
+ return Header.CalculateLength() + CalculateLength() + Trailer.CalculateLength();
}
- private static string FieldMapToXML(DataDictionary.DataDictionary dd, FieldMap fields, int space)
+ private static string FieldMapToXML(DD? dd, FieldMap fields, int space)
{
StringBuilder s = new StringBuilder();
- string name = string.Empty;
// fields
foreach (var f in fields)
{
s.Append("");
- s.Append("");
+ s.Append("number=\"" + f.Key + "\">");
+ s.Append("");
s.Append("");
}
// now groups
@@ -903,56 +802,54 @@ private static string FieldMapToXML(DataDictionary.DataDictionary dd, FieldMap f
/// ToJSON() helper method.
///
/// an XML string
- private static StringBuilder FieldMapToJSON(StringBuilder sb, DataDictionary.DataDictionary dd, FieldMap fields, bool humanReadableValues)
+ private static StringBuilder FieldMapToJSON(StringBuilder sb, DD? dd, FieldMap fields, bool humanReadableValues)
{
IList numInGroupTagList = fields.GetGroupTags();
- IList numInGroupFieldList = new List();
- string valueDescription = "";
+ IList numInGroupFieldList = new List();
// Non-Group Fields
- foreach (var field in fields)
+ foreach (var (_, field) in fields)
{
- if (QuickFix.Fields.CheckSum.TAG == field.Value.Tag)
+ if (QuickFix.Fields.CheckSum.TAG == field.Tag)
continue; // FIX JSON Encoding does not include CheckSum
- if (numInGroupTagList.Contains(field.Value.Tag))
+ if (numInGroupTagList.Contains(field.Tag))
{
- numInGroupFieldList.Add(field.Value);
+ numInGroupFieldList.Add(field);
continue; // Groups will be handled below
}
- if ((dd != null) && ( dd.FieldsByTag.ContainsKey(field.Value.Tag)))
+ if (dd is not null && dd.FieldsByTag.ContainsKey(field.Tag))
{
- sb.Append("\"" + dd.FieldsByTag[field.Value.Tag].Name + "\":");
- if (humanReadableValues)
- {
- if (dd.FieldsByTag[field.Value.Tag].EnumDict.TryGetValue(field.Value.ToString(), out valueDescription))
+ sb.Append("\"" + dd.FieldsByTag[field.Tag].Name + "\":");
+ if (humanReadableValues) {
+ if (dd.FieldsByTag[field.Tag].EnumDict.TryGetValue(field.ToString(), out var valueDescription))
{
sb.Append("\"" + valueDescription + "\",");
}
else
- sb.Append("\"" + field.Value.ToString() + "\",");
+ sb.Append("\"" + field + "\",");
}
else
{
- sb.Append("\"" + field.Value.ToString() + "\",");
+ sb.Append("\"" + field + "\",");
}
}
else
{
- sb.Append("\"" + field.Value.Tag.ToString() + "\":");
- sb.Append("\"" + field.Value.ToString() + "\",");
+ sb.Append("\"" + field.Tag + "\":");
+ sb.Append("\"" + field + "\",");
}
}
// Group Fields
- foreach(Fields.IField numInGroupField in numInGroupFieldList)
+ foreach(IField numInGroupField in numInGroupFieldList)
{
// The name of the NumInGroup field is the key of the JSON list containing the Group items
- if ((dd != null) && ( dd.FieldsByTag.ContainsKey(numInGroupField.Tag)))
+ if (dd is not null && dd.FieldsByTag.ContainsKey(numInGroupField.Tag))
sb.Append("\"" + dd.FieldsByTag[numInGroupField.Tag].Name + "\":[");
else
- sb.Append("\"" + numInGroupField.Tag.ToString() + "\":[");
+ sb.Append("\"" + numInGroupField.Tag + "\":[");
// Populate the JSON list with the Group items
for (int counter = 1; counter <= fields.GroupCount(numInGroupField.Tag); counter++)
@@ -963,13 +860,13 @@ private static StringBuilder FieldMapToJSON(StringBuilder sb, DataDictionary.Dat
}
// Remove trailing comma
- if (sb.Length > 0 && sb[sb.Length - 1] == ',')
+ if (sb.Length > 0 && sb[^1] == ',')
sb.Remove(sb.Length - 1, 1);
sb.Append("],");
}
// Remove trailing comma
- if (sb.Length > 0 && sb[sb.Length - 1] == ',')
+ if (sb.Length > 0 && sb[^1] == ',')
sb.Remove(sb.Length - 1, 1);
return sb;
@@ -979,72 +876,43 @@ private static StringBuilder FieldMapToJSON(StringBuilder sb, DataDictionary.Dat
/// Get a representation of the message as an XML string.
/// (NOTE: this is just an ad-hoc XML; it is NOT FIXML.)
///
+ /// if null, then field names cannot and will not be in the output
/// an XML string
- public string ToXML()
- {
- return ToXML(this.ApplicationDataDictionary);
- }
-
- ///
- /// Get a representation of the message as an XML string.
- /// (NOTE: this is just an ad-hoc XML; it is NOT FIXML.)
- ///
- /// an XML string
- public string ToXML(DataDictionary.DataDictionary dd)
+ public string ToXML(DD? dataDictionary = null)
{
StringBuilder s = new StringBuilder();
s.Append("");
s.Append("");
- s.Append(FieldMapToXML(dd, Header, 4));
+ s.Append(FieldMapToXML(dataDictionary, Header, 4));
s.Append("");
s.Append("");
- s.Append(FieldMapToXML(dd, this, 4));
+ s.Append(FieldMapToXML(dataDictionary, this, 4));
s.Append("");
s.Append("");
- s.Append(FieldMapToXML(dd, Trailer, 4));
+ s.Append(FieldMapToXML(dataDictionary, Trailer, 4));
s.Append("");
s.Append("");
return s.ToString();
}
- ///
- /// Get a representation of the message as a string in FIX JSON Encoding.
- /// See: https://github.com/FIXTradingCommunity/fix-json-encoding-spec
- ///
- /// a JSON string
- public string ToJSON()
- {
- return ToJSON(this.ApplicationDataDictionary, false);
- }
-
-
- ///
- /// Get a representation of the message as a string in FIX JSON Encoding.
- /// See: https://github.com/FIXTradingCommunity/fix-json-encoding-spec
- ///
- /// Per the FIX JSON Encoding spec, tags are converted to human-readable form, but values are not.
- /// If you want human-readable values, set humanReadableValues to true.
- ///
- /// a JSON string
- public string ToJSON(bool humanReadableValues)
- {
- return ToJSON(this.ApplicationDataDictionary, humanReadableValues);
- }
-
///
/// Get a representation of the message as a string in FIX JSON Encoding.
/// See: https://github.com/FIXTradingCommunity/fix-json-encoding-spec
///
/// Per the FIX JSON Encoding spec, tags are converted to human-readable form, but values are not.
- /// If you want human-readable values, set humanReadableValues to true.
///
+ /// Needed if you want tag names emitted or humanReadableValues to work
+ ///
+ /// True will cause enums to be converted to human strings.
+ /// Will not (and cannot!) work if dataDictionary is null.
+ ///
/// a JSON string
- public string ToJSON(DataDictionary.DataDictionary dd, bool humanReadableValues)
+ public string ToJSON(DD? dataDictionary = null, bool humanReadableValues = false)
{
StringBuilder sb = new StringBuilder().Append("{").Append("\"Header\":{");
- FieldMapToJSON(sb, dd, Header, humanReadableValues).Append("},\"Body\":{");
- FieldMapToJSON(sb, dd, this, humanReadableValues).Append("},\"Trailer\":{");
- FieldMapToJSON(sb, dd, Trailer, humanReadableValues).Append("}}");
+ FieldMapToJSON(sb, dataDictionary, Header, humanReadableValues).Append("},\"Body\":{");
+ FieldMapToJSON(sb, dataDictionary, this, humanReadableValues).Append("},\"Trailer\":{");
+ FieldMapToJSON(sb, dataDictionary, Trailer, humanReadableValues).Append("}}");
return sb.ToString();
}
}
diff --git a/QuickFIXn/Message/Trailer.cs b/QuickFIXn/Message/Trailer.cs
new file mode 100644
index 000000000..4db07dcea
--- /dev/null
+++ b/QuickFIXn/Message/Trailer.cs
@@ -0,0 +1,26 @@
+#nullable enable
+using System;
+using System.Text;
+using QuickFix.Fields;
+
+namespace QuickFix {
+ public class Trailer : FieldMap {
+ public int[] TRAILER_FIELD_ORDER = { Tags.SignatureLength, Tags.Signature, Tags.CheckSum };
+
+ public Trailer()
+ : base() {
+ }
+
+ public Trailer(Trailer src)
+ : base(src) {
+ }
+
+ public override string CalculateString() {
+ return base.CalculateString(new StringBuilder(), TRAILER_FIELD_ORDER);
+ }
+
+ public override string CalculateString(StringBuilder sb, int[] preFields) {
+ return base.CalculateString(sb, TRAILER_FIELD_ORDER);
+ }
+ }
+}
diff --git a/QuickFIXn/MessageBuilder.cs b/QuickFIXn/MessageBuilder.cs
index c34446fb6..1441d3e77 100644
--- a/QuickFIXn/MessageBuilder.cs
+++ b/QuickFIXn/MessageBuilder.cs
@@ -50,7 +50,8 @@ internal Message Build()
_validateLengthAndChecksum,
_sessionDD,
_appDD,
- _msgFactory);
+ _msgFactory,
+ ignoreBody: false);
_message = message;
return _message;
}
diff --git a/QuickFIXn/Session.cs b/QuickFIXn/Session.cs
index bb32efb12..181cd54db 100755
--- a/QuickFIXn/Session.cs
+++ b/QuickFIXn/Session.cs
@@ -780,7 +780,7 @@ protected void NextResendRequest(Message resendReq)
foreach (string msgStr in messages)
{
Message msg = new Message();
- msg.FromString(msgStr, true, this.SessionDataDictionary, this.ApplicationDataDictionary, _msgFactory);
+ msg.FromString(msgStr, true, this.SessionDataDictionary, this.ApplicationDataDictionary, _msgFactory, ignoreBody: false);
msgSeqNum = msg.Header.GetULong(Tags.MsgSeqNum);
if ((current != msgSeqNum) && begin == 0)
diff --git a/QuickFIXn/SocketReader.cs b/QuickFIXn/SocketReader.cs
index 93f822518..aecdcf508 100755
--- a/QuickFIXn/SocketReader.cs
+++ b/QuickFIXn/SocketReader.cs
@@ -124,7 +124,7 @@ private void OnMessageFound(string msg)
{
if (null == _qfSession)
{
- _qfSession = Session.LookupSession(Message.GetReverseSessionID(msg));
+ _qfSession = Session.LookupSession(Message.GetReverseSessionId(msg));
if (null == _qfSession)
{
this.Log("ERROR: Disconnecting; received message for unknown session: " + msg);
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 075fd8a20..d19308e0c 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -14,10 +14,27 @@ What's New
**Breaking changes**
* #768 - span-ify parser (Rob-Hague) - makes a change to QuickFix.Parser interface, which isn't likely to affect users
-* #820 - cleanup/nullable-ize files (gbirchmeier) - changed some Session Generate* functions to return void instead of null.
- Very low likelihood that any user code will be affected.
+* #820 - cleanup/nullable-ize initiator/acceptor files (gbirchmeier) -
+ changed some Session Generate* functions to return void instead of null,
+ very low likelihood that any user code will be affected.
* #821 - delete dead code: ByteSizeString class & test, do-nothing ConfigTest (gbirchmeier) -
ByteSizeString is public, but probably no one uses it
+* #822 - cleanup/nullable-ize Message/ classes (gbirchmeier)
+ * FieldMap: getFieldOrder() deleted. Just call FieldOrder.
+ * FieldMap: GetGroup(int num, Group group) now returns null instead of redundant Group
+ * Group: rename Field to CounterField
+ * Message: changed `SOH`'s type from string to char
+ * Message: ctor Message(string msgstr, DataDictionary.DataDictionary dataDictionary, bool validate) deleted.
+ You can use the 2-DD version, though for FIX4 those DDs will be the same.
+ * Message: ExtractField()'s 2 DD params removed. They were never used.
+ * Message: static GetFieldOrDefault() changed to private. Unlikely anyone will notice.
+ * Message: static GetReverseSessionID(Message) changed to private. Unlikely anyone will notice.
+ (The version with the string param is still public)
+ * Message: FromStringHeader renamed and made private. Unlikely anyone will notice.
+ * Message: ToXML() and ToJSON() require DD params for any tag/enum translation.
+ (Message no longer stores a DD instance var.)
+ These functions are new, probably not widely used yet.
+ Function docs are now clear on this behavior.
**Non-breaking changes**
* #400 - added DDTool, a C#-based codegen, and deleted Ruby-based generator (gbirchmeier)
diff --git a/UnitTests/DataDictionaryTests.cs b/UnitTests/DataDictionaryTests.cs
index 63b8d394b..40446c5b6 100644
--- a/UnitTests/DataDictionaryTests.cs
+++ b/UnitTests/DataDictionaryTests.cs
@@ -13,6 +13,8 @@ public class DataDictionaryTests
{
private QuickFix.IMessageFactory _defaultMsgFactory = new QuickFix.DefaultMessageFactory();
+ private const char NUL = Message.SOH;
+
[Test]
public void VersionTest()
{
@@ -305,12 +307,11 @@ public void CheckGroupCountTest()
QuickFix.FIX42.NewOrderSingle n = new QuickFix.FIX42.NewOrderSingle();
- string nul = Message.SOH;
- string s = "8=FIX.4.2" + nul + "9=148" + nul + "35=D" + nul + "34=2" + nul + "49=TW" + nul + "52=20111011-15:06:23.103" + nul + "56=ISLD" + nul
- + "11=ID" + nul + "21=1" + nul + "40=1" + nul + "54=1" + nul + "38=200.00" + nul + "55=INTC" + nul
- + "386=3" + nul + "336=PRE-OPEN" + nul + "336=AFTER-HOURS" + nul
- + "60=20111011-15:06:23.103" + nul
- + "10=35" + nul;
+ string s = "8=FIX.4.2" + NUL + "9=148" + NUL + "35=D" + NUL + "34=2" + NUL + "49=TW" + NUL + "52=20111011-15:06:23.103" + NUL + "56=ISLD" + NUL
+ + "11=ID" + NUL + "21=1" + NUL + "40=1" + NUL + "54=1" + NUL + "38=200.00" + NUL + "55=INTC" + NUL
+ + "386=3" + NUL + "336=PRE-OPEN" + NUL + "336=AFTER-HOURS" + NUL
+ + "60=20111011-15:06:23.103" + NUL
+ + "10=35" + NUL;
n.FromString(s, true, dd, dd, _defaultMsgFactory);
@@ -333,7 +334,7 @@ public void ValidateWrongType()
"11=clordid", "55=sym", "54=1", "60=20110909-09:09:09.999", "40=1",
"38=failboat", // should be a decimal
"10=64"};
- string msgStr = String.Join(Message.SOH, msgFields) + Message.SOH;
+ string msgStr = string.Join(Message.SOH, msgFields) + Message.SOH;
string msgType = "D";
string beginString = "FIX.4.4";
@@ -351,10 +352,9 @@ public void ValidateWithRepeatingGroupTest()
dd.LoadFIXSpec("FIX42");
QuickFix.FIX42.MessageFactory f = new QuickFix.FIX42.MessageFactory();
- string nul = Message.SOH;
- string msgStr = "8=FIX.4.2" + nul + "9=87" + nul + "35=B" + nul + "34=3" + nul + "49=CLIENT1" + nul
- + "52=20111012-22:15:55.474" + nul + "56=EXECUTOR" + nul + "148=AAAAAAA" + nul
- + "33=2" + nul + "58=L1" + nul + "58=L2" + nul + "10=016" + nul;
+ string msgStr = "8=FIX.4.2" + NUL + "9=87" + NUL + "35=B" + NUL + "34=3" + NUL + "49=CLIENT1" + NUL
+ + "52=20111012-22:15:55.474" + NUL + "56=EXECUTOR" + NUL + "148=AAAAAAA" + NUL
+ + "33=2" + NUL + "58=L1" + NUL + "58=L2" + NUL + "10=016" + NUL;
QuickFix.Fields.MsgType msgType = Message.IdentifyType(msgStr);
string beginString = Message.ExtractBeginString(msgStr);
@@ -380,10 +380,10 @@ public void ValidateGroupBeginsGroup()
+ "1111=mundane|5555=magicfield|6660=1|7770=2|7711=Hoppy|7712=brown|"
+ "7711=Floppy|7712=white|6661=abracadabra|10=48|";
// note: length and checksum might be garbage
- string msgStr = pipedStr.Replace("|", Message.SOH);
+ string msgStr = pipedStr.Replace('|', Message.SOH);
string beginString = Message.ExtractBeginString(msgStr);
- Message msg = new Message(msgStr, dd, false);
+ Message msg = new Message(msgStr, dd, dd, false);
// true param means body-only, i.e. don't validate length/checksum
dd.Validate(msg, true, beginString, "magic");
@@ -414,7 +414,7 @@ public void ValidateWrongTypeInRepeatingGroup()
"146=1", // InstrmtMDReqGrp
"55=sym",
"10=91"};
- string msgStr = String.Join(Message.SOH, msgFields) + Message.SOH;
+ string msgStr = string.Join(Message.SOH, msgFields) + Message.SOH;
string msgType = "V";
string beginString = "FIX.4.4";
@@ -440,7 +440,7 @@ public void ValidateWrongTypeInNestedRepeatingGroup()
"757=nested2partyid",
"759=failboat", // supposed to be a int
"10=48"};
- string msgStr = String.Join(Message.SOH, msgFields) + Message.SOH;
+ string msgStr = string.Join(Message.SOH, msgFields) + Message.SOH;
string msgType = "J";
string beginString = "FIX.4.4";
@@ -460,7 +460,7 @@ public void ValidateDateAndTimeFields()
string[] msgFields = { "8=FIX.4.4", "9=104", "35=W", "34=3", "49=sender", "52=20110909-09:09:09.999", "56=target",
"55=sym", "268=1", "269=0", "272=20111012", "273=22:15:30.444", "10=19" };
- string msgStr = String.Join(Message.SOH, msgFields) + Message.SOH;
+ string msgStr = string.Join(Message.SOH, msgFields) + Message.SOH;
string msgType = "W";
string beginString = "FIX.4.4";
@@ -490,7 +490,7 @@ public void ValidateDateTime_Invalid()
// intentionally invalid SendingTime (52/DateTime)
string[] msgFields = { "8=FIX.4.4", "9=91", "35=W", "34=3", "49=sender", "52=20110909", "56=target",
"55=sym", "268=1", "269=0", "272=20111012", "273=22:15:30.444", "10=51" };
- string msgStr = String.Join(Message.SOH, msgFields) + Message.SOH;
+ string msgStr = string.Join(Message.SOH, msgFields) + Message.SOH;
string msgType = "W";
string beginString = "FIX.4.4";
@@ -511,7 +511,7 @@ public void ValidateDateOnly_Invalid()
// intentionally invalid MDEntryDate (272/DateOnly)
string[] msgFields = { "8=FIX.4.4", "9=117", "35=W", "34=3", "49=sender", "52=20110909-09:09:09.999", "56=target",
"55=sym", "268=1", "269=0", "272=20111012-22:15:30.444", "273=22:15:30.444", "10=175" };
- string msgStr = String.Join(Message.SOH, msgFields) + Message.SOH;
+ string msgStr = string.Join(Message.SOH, msgFields) + Message.SOH;
string msgType = "W";
string beginString = "FIX.4.4";
@@ -532,7 +532,7 @@ public void ValidateTimeOnly_Invalid()
// intentionally invalid MDEntryTime (272/TimeOnly)
string[] msgFields = { "8=FIX.4.4", "9=113", "35=W", "34=3", "49=sender", "52=20110909-09:09:09.999", "56=target",
"55=sym", "268=1", "269=0", "272=20111012", "273=20111012-22:15:30.444", "10=200" };
- string msgStr = String.Join(Message.SOH, msgFields) + Message.SOH;
+ string msgStr = string.Join(Message.SOH, msgFields) + Message.SOH;
string msgType = "W";
string beginString = "FIX.4.4";
@@ -563,7 +563,7 @@ public void OptionalComponentRequiredField()
string[] msgFields = { "8=FIX.4.4", "9=77", "35=AD", "34=3", "49=sender", "52=20110909-09:09:09.999", "56=target",
"568=tradereqid", "569=0", "10=109" };
- string msgStr = String.Join(Message.SOH, msgFields) + Message.SOH;
+ string msgStr = string.Join(Message.SOH, msgFields) + Message.SOH;
string msgType = "AD";
string beginString = "FIX.4.4";
@@ -583,7 +583,7 @@ public void RequiredComponentRequiredField()
string[] msgFields = { "8=FIX.4.4", "9=76", "35=7", "34=3", "49=sender", "52=20110909-09:09:09.999", "56=target",
"2=AdvId", "5=N", "4=B", "53=1", "10=138" };
- string msgStr = String.Join(Message.SOH, msgFields) + Message.SOH;
+ string msgStr = string.Join(Message.SOH, msgFields) + Message.SOH;
string msgType = "7";
string beginString = "FIX.4.4";
@@ -628,13 +628,13 @@ public void ValidateMultipleValueStringType()
"55=sym",
"268=1", "269=0", "270=123.23", "271=2", "277=A B",
"10=213"};
- string msgStr = String.Join( Message.SOH, msgFields ) + Message.SOH;
+ string msgStr = string.Join( Message.SOH, msgFields ) + Message.SOH;
string msgType = "W";
string beginString = "FIX.4.4";
Message message = f.Create( beginString, msgType );
- message.FromString( msgStr, true, dd, dd );
+ message.FromString(msgStr, true, dd, dd);
dd.Validate( message, beginString, msgType );
}
@@ -650,13 +650,13 @@ public void ValidateMultipleValueStringType_Invalid()
"55=sym",
"268=1", "269=0", "270=123.23", "271=2", "277=A 1",
"10=196"};
- string msgStr = String.Join( Message.SOH, msgFields ) + Message.SOH;
+ string msgStr = string.Join( Message.SOH, msgFields ) + Message.SOH;
string msgType = "W";
string beginString = "FIX.4.4";
Message message = f.Create( beginString, msgType );
- message.FromString( msgStr, true, dd, dd );
+ message.FromString(msgStr, true, dd, dd);
Assert.That(() => dd.Validate(message, beginString, msgType), Throws.TypeOf());
}
@@ -670,7 +670,7 @@ public void ValidateTagSpecifiedWithoutAValue()
string[] msgFields = {"8=FIX.4.2", "9=70", "35=B", "34=3", "49=sender", "52=20110909-09:09:09.999", "56=target",
"358=", "148=", "33=0", "10=150"};
- string msgStr = String.Join(Message.SOH, msgFields) + Message.SOH;
+ string msgStr = string.Join(Message.SOH, msgFields) + Message.SOH;
string msgType = "B";
string beginString = "FIX.4.2";
@@ -712,10 +712,7 @@ XmlNode MakeNode(string xmlString)
doc.LoadXml(xmlString);
return doc.DocumentElement;
}
- else
- {
- return doc.CreateTextNode(xmlString);
- }
+ return doc.CreateTextNode(xmlString);
}
[Test]
diff --git a/UnitTests/FieldMapTests.cs b/UnitTests/FieldMapTests.cs
index 0a875933f..25ba7ea4f 100644
--- a/UnitTests/FieldMapTests.cs
+++ b/UnitTests/FieldMapTests.cs
@@ -300,7 +300,7 @@ public void SimpleFieldOrderTest()
public void GroupDelimTest()
{
Group g1 = new Group(100, 200);
- Assert.AreEqual(100, g1.Field); //counter
+ Assert.AreEqual(100, g1.CounterField); //counter
Assert.AreEqual(200, g1.Delim);
g1.SetField(new StringField(200, "delim!"));
diff --git a/UnitTests/GroupTests.cs b/UnitTests/GroupTests.cs
index 990855a20..419b4d70a 100644
--- a/UnitTests/GroupTests.cs
+++ b/UnitTests/GroupTests.cs
@@ -53,7 +53,7 @@ public void GroupClone()
Assert.AreEqual(linesGroup.Text.Obj, clone.Text.Obj);
Assert.AreEqual(linesGroup.EncodedText.Obj, clone.EncodedText.Obj);
Assert.AreEqual(linesGroup.Delim, clone.Delim);
- Assert.AreEqual(linesGroup.Field, clone.Field);
+ Assert.AreEqual(linesGroup.CounterField, clone.CounterField);
Assert.AreEqual(linesGroup.FieldOrder, clone.FieldOrder);
}
}
diff --git a/UnitTests/MessageTests.cs b/UnitTests/MessageTests.cs
index 0be9e15af..a8b5dcfda 100644
--- a/UnitTests/MessageTests.cs
+++ b/UnitTests/MessageTests.cs
@@ -961,7 +961,7 @@ public void ChecksumIsLastFieldOfTrailer()
msg.Trailer.SetField(new Signature("woot"));
msg.Trailer.SetField(new SignatureLength(4));
- string foo = msg.ToString().Replace(Message.SOH, "|");
+ string foo = msg.ToString().Replace(Message.SOH, '|');
StringAssert.EndsWith("|10=099|", foo);
}
diff --git a/UnitTests/MessageToXmlTests.cs b/UnitTests/MessageToXmlTests.cs
index 365e38be7..7596b5b4d 100644
--- a/UnitTests/MessageToXmlTests.cs
+++ b/UnitTests/MessageToXmlTests.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
using System.IO;
using NUnit.Framework;
using QuickFix;
@@ -48,13 +47,16 @@ public void ToXMLWithGroupsTest()
"448=TFOLIO:6804469", "447=D", "452=36",
"10=152"
};
- string msgStr = String.Join(Message.SOH, msgFields) + Message.SOH;
+ string msgStr = string.Join(Message.SOH, msgFields) + Message.SOH;
QuickFix.FIX44.ExecutionReport msg = new QuickFix.FIX44.ExecutionReport();
msg.FromString(msgStr, true, dd, dd, null); // <-- null factory!
string expected = @"";
- Assert.AreEqual(expected, msg.ToXML());
+ Assert.AreEqual(expected, msg.ToXML(dataDictionary: dd));
+
+ // If no DD, then output can't have field names
+ StringAssert.Contains(@"", msg.ToXML());
}
[Test]
@@ -81,13 +83,19 @@ public void ToJSONWithGroupsTest()
"448=TFOLIO:6804469", "447=D", "452=36",
"10=152"
};
- string msgStr = String.Join(Message.SOH, msgFields) + Message.SOH;
+ string msgStr = string.Join(Message.SOH, msgFields) + Message.SOH;
QuickFix.FIX44.ExecutionReport msg = new QuickFix.FIX44.ExecutionReport();
msg.FromString(msgStr, true, dd, dd, null); // <-- null factory!
string expected = "{\"Header\":{\"BeginString\":\"FIX.4.4\",\"BodyLength\":\"638\",\"MsgSeqNum\":\"360\",\"MsgType\":\"8\",\"SenderCompID\":\"BLPTSOX\",\"SendingTime\":\"20130321-15:21:23\",\"TargetCompID\":\"THINKTSOX\",\"TargetSubID\":\"6804469\",\"DeliverToCompID\":\"ZERO\"},\"Body\":{\"AvgPx\":\"122.255\",\"ClOrdID\":\"61101189\",\"CumQty\":\"1990000\",\"Currency\":\"GBP\",\"ExecID\":\"VCON:20130321:50018:5:12\",\"SecurityIDSource\":\"4\",\"LastPx\":\"122.255\",\"LastQty\":\"1990000\",\"OrderID\":\"116\",\"OrderQty\":\"1990000\",\"OrdStatus\":\"2\",\"SecurityID\":\"GB0032452392\",\"Side\":\"1\",\"Symbol\":\"[N/A]\",\"TransactTime\":\"20130321-15:21:23\",\"SettlDate\":\"20130322\",\"TradeDate\":\"20130321\",\"Issuer\":\"UK TSY 4 1/4% 2036\",\"NetMoney\":\"2436321.85\",\"ExecType\":\"F\",\"LeavesQty\":\"0\",\"NumDaysInterest\":\"15\",\"AccruedInterestAmt\":\"3447.35\",\"OrderQty2\":\"0\",\"SecondaryOrderID\":\"3739:20130321:50018:5\",\"CouponRate\":\"0.0425\",\"Factor\":\"1\",\"Yield\":\"0.0291371041\",\"Concession\":\"0\",\"GrossTradeAmt\":\"2432874.5\",\"PriceType\":\"1\",\"CountryOfIssue\":\"GB\",\"MaturityDate\":\"20360307\",\"NoPartyIDs\":[{\"PartyIDSource\":\"D\",\"PartyID\":\"VCON\",\"PartyRole\":\"1\",\"NoPartySubIDs\":[{\"PartySubID\":\"14\",\"PartySubIDType\":\"4\"}]},{\"PartyIDSource\":\"D\",\"PartyID\":\"TFOLIO:6804469\",\"PartyRole\":\"12\"},{\"PartyIDSource\":\"D\",\"PartyID\":\"TFOLIO\",\"PartyRole\":\"11\"},{\"PartyIDSource\":\"D\",\"PartyID\":\"THINKFOLIO LTD\",\"PartyRole\":\"13\"},{\"PartyIDSource\":\"D\",\"PartyID\":\"SXT\",\"PartyRole\":\"16\"},{\"PartyIDSource\":\"D\",\"PartyID\":\"TFOLIO:6804469\",\"PartyRole\":\"36\"}]},\"Trailer\":{}}";
- Assert.AreEqual(expected, msg.ToJSON());
+ Assert.AreEqual(expected, msg.ToJSON(dataDictionary: dd, humanReadableValues: false));
+
+ // emit enums as human-readable strings
+ StringAssert.Contains("\"MsgType\":\"EXECUTION_REPORT\"", msg.ToJSON(dataDictionary: dd, humanReadableValues: true));
+
+ // Without a DD: tags aren't translated, and you don't get enums either
+ StringAssert.Contains("\"35\":\"8\"", msg.ToJSON(dataDictionary: null, humanReadableValues: true));
}
}
}