diff --git a/QuickFIXn/DataDictionary/DDField.cs b/QuickFIXn/DataDictionary/DDField.cs
index f19f818ff..ee775be5b 100644
--- a/QuickFIXn/DataDictionary/DDField.cs
+++ b/QuickFIXn/DataDictionary/DDField.cs
@@ -13,22 +13,22 @@ public class DDField
///
/// dictionary of enum=>description values
///
- public DDField(int tag, String name, IReadOnlyDictionary enums, String fixFldType)
+ public DDField(int tag, string name, IReadOnlyDictionary enums, string fixFldType)
{
this.Tag = tag;
this.Name = name;
this.EnumDict = enums.ToFrozenDictionary();
this.FixFldType = fixFldType;
- this.FieldType = FieldTypeFromFix(this.FixFldType, out bool isMVFWE);
- this.IsMultipleValueFieldWithEnums = isMVFWE;
+ this.FieldType = FieldTypeFromFix(this.FixFldType, out bool isMultipleValueFieldWithEnums);
+ this.IsMultipleValueFieldWithEnums = isMultipleValueFieldWithEnums;
}
public int Tag { get; private set; }
- public String Name { get; private set; }
+ public string Name { get; private set; }
- public IReadOnlyDictionary EnumDict { get; }
+ public IReadOnlyDictionary EnumDict { get; }
- public String FixFldType { get; private set; }
+ public string FixFldType { get; private set; }
public Type FieldType { get; private set; }
///
@@ -36,14 +36,14 @@ public DDField(int tag, String name, IReadOnlyDictionary enums,
///
public bool IsMultipleValueFieldWithEnums { get; private set; }
- public Boolean HasEnums()
+ public bool HasEnums()
{
return EnumDict.Count > 0;
}
- private Type FieldTypeFromFix(String type, out bool multipleValueFieldWithEnums)
+ private Type FieldTypeFromFix(string type, out bool isMultipleValueFieldWithEnums)
{
- multipleValueFieldWithEnums = false;
+ isMultipleValueFieldWithEnums = false;
switch (type)
{
@@ -54,9 +54,9 @@ private Type FieldTypeFromFix(String type, out bool multipleValueFieldWithEnums)
case "AMT": return typeof(Fields.DecimalField);
case "QTY": return typeof(Fields.DecimalField);
case "CURRENCY": return typeof(Fields.StringField);
- case "MULTIPLEVALUESTRING": multipleValueFieldWithEnums = true; return typeof(Fields.StringField);
- case "MULTIPLESTRINGVALUE": multipleValueFieldWithEnums = true; return typeof(Fields.StringField);
- case "MULTIPLECHARVALUE": multipleValueFieldWithEnums = true; return typeof(Fields.StringField);
+ case "MULTIPLEVALUESTRING": isMultipleValueFieldWithEnums = true; return typeof(Fields.StringField);
+ case "MULTIPLESTRINGVALUE": isMultipleValueFieldWithEnums = true; return typeof(Fields.StringField);
+ case "MULTIPLECHARVALUE": isMultipleValueFieldWithEnums = true; return typeof(Fields.StringField);
case "EXCHANGE": return typeof(Fields.StringField);
case "UTCTIMESTAMP": return typeof(Fields.DateTimeField);
case "BOOLEAN": return typeof(Fields.BooleanField);
diff --git a/QuickFIXn/DataDictionary/DDMap.cs b/QuickFIXn/DataDictionary/DDMap.cs
index 0f1f5cee6..a68e5fe96 100644
--- a/QuickFIXn/DataDictionary/DDMap.cs
+++ b/QuickFIXn/DataDictionary/DDMap.cs
@@ -1,68 +1,66 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-namespace QuickFix.DataDictionary
-{
- ///
- /// Represents the DD definition for a message type
- ///
- public class DDMap : IFieldMapSpec
- {
- public Dictionary Fields = new Dictionary();
- public Dictionary Groups = new Dictionary();
- public HashSet ReqFields = new HashSet();
+namespace QuickFix.DataDictionary;
- public void AddField(DDField fld)
- {
- Fields.Add(fld.Tag, fld);
- }
+///
+/// Represents the DD definition for a message type
+///
+public class DDMap : IFieldMapSpec
+{
+ public Dictionary Fields = new();
+ public Dictionary Groups = new();
+ public HashSet ReqFields = [];
- public void AddGroup(DDGrp grp)
- {
- Groups.Add(grp.Delim, grp);
- }
+ public void AddField(DDField fld)
+ {
+ Fields.Add(fld.Tag, fld);
+ }
- public Boolean IsGroup(int tag)
- {
- return Groups.ContainsKey(tag);
- }
+ public void AddGroup(DDGrp grp)
+ {
+ Groups.Add(grp.Delim, grp);
+ }
- public Boolean IsField(int tag)
- {
- return Fields.ContainsKey(tag);
- }
+ public Boolean IsGroup(int tag)
+ {
+ return Groups.ContainsKey(tag);
+ }
- public DDGrp GetGroup(int tag)
- {
- return Groups[tag];
- }
+ public Boolean IsField(int tag)
+ {
+ return Fields.ContainsKey(tag);
+ }
- ///
- /// Same as GetGroup, just a more-general return type.
- ///
- ///
- ///
- public IGroupSpec GetGroupSpec(int tag)
- {
- return Groups[tag];
- }
+ public DDGrp GetGroup(int tag)
+ {
+ return Groups[tag];
}
///
- /// Represents the DD definition for a group type
+ /// Same as GetGroup, just a more-general return type.
///
- public class DDGrp : DDMap, IGroupSpec
+ ///
+ ///
+ public IGroupSpec GetGroupSpec(int tag)
+ {
+ return Groups[tag];
+ }
+}
+
+///
+/// Represents the DD definition for a group type
+///
+public class DDGrp : DDMap, IGroupSpec
+{
+ public int NumFld { get; set; }
+ public int Delim { get; set; }
+ public Boolean Required = false;
+ public DDGrp() : base()
{
- public int NumFld { get; set; }
- public int Delim { get; set; }
- public Boolean Required = false;
- public DDGrp() : base()
- {
- Delim = 0;
- NumFld = 0;
- Required = false;
- }
+ Delim = 0;
+ NumFld = 0;
+ Required = false;
}
}
+
diff --git a/QuickFIXn/DataDictionary/DictionaryParseException.cs b/QuickFIXn/DataDictionary/DictionaryParseException.cs
index 4c74c757c..aba8dbc14 100644
--- a/QuickFIXn/DataDictionary/DictionaryParseException.cs
+++ b/QuickFIXn/DataDictionary/DictionaryParseException.cs
@@ -1,13 +1,12 @@
using System;
-namespace QuickFix
+namespace QuickFix.DataDictionary;
+
+public class DictionaryParseException : ApplicationException
{
- public class DictionaryParseException : ApplicationException
- {
- public DictionaryParseException() { }
- public DictionaryParseException(string message)
- : base(message) { }
- public DictionaryParseException(string message, System.Exception inner)
- : base(message, inner) { }
- }
+ public DictionaryParseException() { }
+ public DictionaryParseException(string message)
+ : base(message) { }
+ public DictionaryParseException(string message, System.Exception inner)
+ : base(message, inner) { }
}
diff --git a/QuickFIXn/DataDictionary/IFieldMapSpec.cs b/QuickFIXn/DataDictionary/IFieldMapSpec.cs
index 3c3091b79..da3637770 100644
--- a/QuickFIXn/DataDictionary/IFieldMapSpec.cs
+++ b/QuickFIXn/DataDictionary/IFieldMapSpec.cs
@@ -1,31 +1,27 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-namespace QuickFix.DataDictionary
+namespace QuickFix.DataDictionary;
+
+public interface IFieldMapSpec
{
- public interface IFieldMapSpec
- {
- ///
- /// Returns true if this tag is for a group-counter field defined for this IFieldMapSpec
- ///
- ///
- ///
- Boolean IsGroup(int tag);
+ ///
+ /// Returns true if this tag is for a group-counter field defined for this IFieldMapSpec
+ ///
+ ///
+ ///
+ Boolean IsGroup(int tag);
+
+ ///
+ /// Returns true if this tag is for a field defined for this IFieldMapSpec
+ ///
+ ///
+ ///
+ Boolean IsField(int tag);
- ///
- /// Returns true if this tag is for a field defined for this IFieldMapSpec
- ///
- ///
- ///
- Boolean IsField(int tag);
-
- ///
- /// Get the IGroupSpec that corresponds to this group-counter tag
- ///
- ///
- ///
- IGroupSpec GetGroupSpec(int tag);
- }
+ ///
+ /// Get the IGroupSpec that corresponds to this group-counter tag
+ ///
+ ///
+ ///
+ IGroupSpec GetGroupSpec(int tag);
}
diff --git a/QuickFIXn/DataDictionary/IGroupSpec.cs b/QuickFIXn/DataDictionary/IGroupSpec.cs
index 7c1f6ba29..a907ab7c5 100644
--- a/QuickFIXn/DataDictionary/IGroupSpec.cs
+++ b/QuickFIXn/DataDictionary/IGroupSpec.cs
@@ -1,12 +1,11 @@
using System;
-namespace QuickFix.DataDictionary
+namespace QuickFix.DataDictionary;
+
+public interface IGroupSpec : IFieldMapSpec
{
- public interface IGroupSpec : IFieldMapSpec
- {
- ///
- /// The tag of the delimiter field, i.e. the first field of each group member
- ///
- int Delim { get; set; }
- }
+ ///
+ /// The tag of the delimiter field, i.e. the first field of each group member
+ ///
+ int Delim { get; set; }
}
diff --git a/QuickFIXn/DataDictionary/InvalidMessageTypeException.cs b/QuickFIXn/DataDictionary/InvalidMessageTypeException.cs
index 4c9587531..3d304c176 100644
--- a/QuickFIXn/DataDictionary/InvalidMessageTypeException.cs
+++ b/QuickFIXn/DataDictionary/InvalidMessageTypeException.cs
@@ -1,19 +1,18 @@
using System;
-namespace QuickFix
+namespace QuickFix.DataDictionary;
+
+[Obsolete("This class will be removed in 1.16 (because it's unused)")]
+public class InvalidMessageTypeException : ApplicationException
{
[Obsolete("This class will be removed in a future release (because it's unused)")]
- public class InvalidMessageTypeException : ApplicationException
- {
- [Obsolete("This class will be removed in a future release (because it's unused)")]
- public InvalidMessageTypeException() { }
+ public InvalidMessageTypeException() { }
- [Obsolete("This class will be removed in a future release (because it's unused)")]
- public InvalidMessageTypeException(string message)
- : base(message) { }
+ [Obsolete("This class will be removed in a future release (because it's unused)")]
+ public InvalidMessageTypeException(string message)
+ : base(message) { }
- [Obsolete("This class will be removed in a future release (because it's unused)")]
- public InvalidMessageTypeException(string message, System.Exception inner)
- : base(message, inner) { }
- }
+ [Obsolete("This class will be removed in a future release (because it's unused)")]
+ public InvalidMessageTypeException(string message, System.Exception inner)
+ : base(message, inner) { }
}
diff --git a/QuickFIXn/DataDictionary/MissingRequiredFieldException.cs b/QuickFIXn/DataDictionary/MissingRequiredFieldException.cs
index ffc1e4bee..626c3a2fe 100644
--- a/QuickFIXn/DataDictionary/MissingRequiredFieldException.cs
+++ b/QuickFIXn/DataDictionary/MissingRequiredFieldException.cs
@@ -1,28 +1,24 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
#pragma warning disable 0628 // Suppress "new protected member declared in sealed class" warning.
-namespace QuickFix
+namespace QuickFix.DataDictionary;
+
+[Obsolete("This class will be removed in 1.16 (because it's unused)")]
+public sealed class MissingRequiredFieldException : ApplicationException
{
[Obsolete("This class will be removed in a future release (because it's unused)")]
- public sealed class MissingRequiredFieldException : ApplicationException
- {
- [Obsolete("This class will be removed in a future release (because it's unused)")]
- public MissingRequiredFieldException() { }
+ public MissingRequiredFieldException() { }
- [Obsolete("This class will be removed in a future release (because it's unused)")]
- public MissingRequiredFieldException(int field)
- : base("Missing required field: " + field.ToString()) { }
+ [Obsolete("This class will be removed in a future release (because it's unused)")]
+ public MissingRequiredFieldException(int field)
+ : base($"Missing required field: {field}") { }
- [Obsolete("This class will be removed in a future release (because it's unused)")]
- public MissingRequiredFieldException(string message)
- : base(message) { }
+ [Obsolete("This class will be removed in a future release (because it's unused)")]
+ public MissingRequiredFieldException(string message)
+ : base(message) { }
- [Obsolete("This class will be removed in a future release (because it's unused)")]
- public MissingRequiredFieldException(string message, System.Exception inner)
- : base(message, inner) { }
- }
+ [Obsolete("This class will be removed in a future release (because it's unused)")]
+ public MissingRequiredFieldException(string message, System.Exception inner)
+ : base(message, inner) { }
}
diff --git a/QuickFIXn/DataDictionary/XMLMsgComponent.cs b/QuickFIXn/DataDictionary/XMLMsgComponent.cs
index 14ef2d3cf..b32e82f66 100644
--- a/QuickFIXn/DataDictionary/XMLMsgComponent.cs
+++ b/QuickFIXn/DataDictionary/XMLMsgComponent.cs
@@ -1,40 +1,40 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-namespace QuickFix
+namespace QuickFix.DataDictionary;
+
+[Obsolete("This class will be removed in 1.16 (because it's unused)")]
+partial class DataDictionaryParser
{
- partial class DataDictionaryParser
+ private sealed class XMLMsgComponent
{
- private sealed class XMLMsgComponent
- {
- public enum TypeEnum { Field, Component, Group };
+ public enum TypeEnum { Field, Component, Group };
- public XMLMsgComponent(string name, bool req, TypeEnum type )
- {
- Name = name;
- Required = req;
- SubComponents = new List();
- ComponentType = type;
- }
- public TypeEnum ComponentType { get; set; }
- public string Name { get; set; }
- public bool Required { get; set; }
- public List SubComponents { get; set; }
+ [Obsolete("This class will be removed in 1.16 (because it's unused)")]
+ public XMLMsgComponent(string name, bool req, TypeEnum type )
+ {
+ Name = name;
+ Required = req;
+ SubComponents = new List();
+ ComponentType = type;
+ }
+ public TypeEnum ComponentType { get; set; }
+ public string Name { get; set; }
+ public bool Required { get; set; }
+ public List SubComponents { get; set; }
- public static TypeEnum GetComponentType(string typestr, string parentName)
+ [Obsolete("This class will be removed in 1.16 (because it's unused)")]
+ public static TypeEnum GetComponentType(string typestr, string parentName)
+ {
+ TypeEnum ctype;
+ switch (typestr)
{
- TypeEnum ctype;
- switch (typestr)
- {
- case "field": ctype = TypeEnum.Field; break;
- case "group": ctype = TypeEnum.Group; break;
- case "component": ctype = TypeEnum.Component; break;
- default: throw new MessageParseError("unknown component in msg: " + parentName);
- }
- return ctype;
+ case "field": ctype = TypeEnum.Field; break;
+ case "group": ctype = TypeEnum.Group; break;
+ case "component": ctype = TypeEnum.Component; break;
+ default: throw new MessageParseError("unknown component in msg: " + parentName);
}
+ return ctype;
}
}
}
diff --git a/QuickFIXn/Message/Message.cs b/QuickFIXn/Message/Message.cs
index f34334844..5fd743cf7 100644
--- a/QuickFIXn/Message/Message.cs
+++ b/QuickFIXn/Message/Message.cs
@@ -49,7 +49,7 @@ public Message(
public Message(string msgstr, DD? transportDict, DD? appDict, bool validate)
: this()
{
- PopulateHeaderFromMessageString(msgstr);
+ PopulateHeaderFromMessageString(msgstr, transportDict);
if (IsAdmin())
FromString(msgstr, validate, transportDict, transportDict, null, false);
else
@@ -90,6 +90,14 @@ public static int ExtractFieldTag(string msgstr, int pos)
return tag;
}
+ ///
+ /// Extract a field whose length is determined by a datalength field
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public static StringField ExtractDataField(string msgstr, int dataLength, ref int pos)
{
try
@@ -116,6 +124,13 @@ public static StringField ExtractDataField(string msgstr, int dataLength, ref in
}
}
+ ///
+ /// Extract a field that ends with SOH
+ ///
+ ///
+ ///
+ ///
+ ///
public static StringField ExtractField(string msgstr, ref int pos)
{
try
@@ -123,7 +138,7 @@ public static StringField ExtractField(string msgstr, ref int pos)
int tagend = msgstr.IndexOf('=', pos);
int tag = Convert.ToInt32(msgstr.Substring(pos, tagend - pos));
pos = tagend + 1;
- int fieldvalend = msgstr.IndexOf((char)1, pos);
+ int fieldvalend = msgstr.IndexOf(SOH, pos);
StringField field = new StringField(tag, msgstr.Substring(pos, fieldvalend - pos));
pos = fieldvalend + 1;
@@ -149,7 +164,19 @@ public static string ExtractBeginString(string msgstr)
return ExtractField(msgstr, ref i).Value;
}
+ [Obsolete("This method is deprecated and will be removed in 1.16. Use IsHeaderField(int tag, DD? dd) instead.")]
public static bool IsHeaderField(int tag)
+ {
+ return IsGenericHeaderField(tag);
+ }
+
+ ///
+ /// Determine if field is a header according to the standard vanilla DD.
+ /// The header list in this function is hardcoded.
+ ///
+ ///
+ ///
+ private static bool IsGenericHeaderField(int tag)
{
switch (tag)
{
@@ -184,12 +211,21 @@ public static bool IsHeaderField(int tag)
return false;
}
}
- public static bool IsHeaderField(int tag, DD? dd)
+
+ ///
+ /// Determine if field is a header field.
+ /// If transportDataDictionary is null, compares against a hard-coded list of header fields as
+ /// specified in the standard FIX data dictionaries.
+ ///
+ ///
+ ///
+ ///
+ public static bool IsHeaderField(int tag, DD? transportDataDictionary)
{
- if (IsHeaderField(tag))
+ if (IsGenericHeaderField(tag))
return true;
- if (dd is not null)
- return dd.IsHeaderField(tag);
+ if (transportDataDictionary is not null)
+ return transportDataDictionary.IsHeaderField(tag);
return false;
}
@@ -319,7 +355,7 @@ public override void Clear()
Trailer.Clear();
}
- private void PopulateHeaderFromMessageString(string msgstr)
+ private void PopulateHeaderFromMessageString(string msgstr, DD? dd)
{
Clear();
@@ -332,7 +368,7 @@ private void PopulateHeaderFromMessageString(string msgstr)
if (count < 3 && Header.HEADER_FIELD_ORDER[count++] != f.Tag)
return;
- if(IsHeaderField(f.Tag))
+ if(IsHeaderField(f.Tag, dd))
Header.SetField(f, false);
else
break;
@@ -368,18 +404,10 @@ public void FromString(
while (pos < msgstr.Length)
{
- StringField? f = null;
-
int fieldTag = ExtractFieldTag(msgstr, pos);
- if (fieldTag == Tags.XmlData)
- {
- if (IsHeaderField(Tags.XmlDataLen))
- f = ExtractDataField(msgstr, Header.GetInt(Tags.XmlDataLen), ref pos);
- else if (IsSetField(Tags.XmlDataLen))
- f = ExtractDataField(msgstr, GetInt(Tags.XmlDataLen), ref pos);
- }
-
- f ??= ExtractField(msgstr, ref pos);
+ StringField f = fieldTag == Tags.XmlData
+ ? ExtractDataField(msgstr, Header.GetInt(Tags.XmlDataLen), ref pos)
+ : ExtractField(msgstr, ref pos);
if (validate && (count < 3) && (Header.HEADER_FIELD_ORDER[count++] != f.Tag))
throw new InvalidMessage("Header fields out of order");
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 2c1b8acbb..4c12d3893 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -34,6 +34,7 @@ What's New
* #841 - experimental support for CME Enhanced Resend (gbirchmeier)
* #961 - new GenerateKeys app to create Example-app SSL certs (dckorben/gbirchmeier)
* #1001 - AcceptanceTests bug: double.Parse with InvariantCulture (gbirchmeier)
+* #562 - deprecate Message.IsHeaderField without transport DD param (gbirchmeier)
### v1.14.0
diff --git a/UnitTests/MessageTests.cs b/UnitTests/MessageTests.cs
index e406fe9ec..0b3cfc20d 100644
--- a/UnitTests/MessageTests.cs
+++ b/UnitTests/MessageTests.cs
@@ -217,9 +217,18 @@ public void ConstructStringFieldOrder()
[Test]
public void IsHeaderFieldTest()
{
- Assert.That(Message.IsHeaderField(Tags.BeginString), Is.EqualTo(true));
- Assert.That(Message.IsHeaderField(Tags.TargetCompID), Is.EqualTo(true));
- Assert.That(Message.IsHeaderField(Tags.Account), Is.EqualTo(false));
+ Assert.That(Message.IsHeaderField(Tags.BeginString, null), Is.EqualTo(true));
+ Assert.That(Message.IsHeaderField(Tags.TargetCompID, null), Is.EqualTo(true));
+ Assert.That(Message.IsHeaderField(Tags.Account, null), Is.EqualTo(false));
+
+ var dd = new QuickFix.DataDictionary.DataDictionary();
+ dd.LoadFIXSpec("FIX44");
+ dd.Header.AddField(
+ new QuickFix.DataDictionary.DDField(901109, "FakeField", new Dictionary(), "STRING"));
+
+ Assert.That(Message.IsHeaderField(Tags.TargetCompID, dd), Is.EqualTo(true));
+ Assert.That(Message.IsHeaderField(Tags.Account, dd), Is.EqualTo(false));
+ Assert.That(Message.IsHeaderField(901109, dd), Is.EqualTo(true));
}
[Test]