Skip to content

Commit 39909fe

Browse files
authored
Provide methods in DataDictionary to get service and extension pack. (#383)
- added basic support for FIX.Latest major version
1 parent 395cac3 commit 39909fe

File tree

3 files changed

+176
-11
lines changed

3 files changed

+176
-11
lines changed

quickfixj-core/src/main/java/quickfix/DataDictionary.java

Lines changed: 89 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ private static Supplier<DocumentBuilderFactory> createDocumentBuilderFactorySupp
9595
private boolean checkUnorderedGroupFields = true;
9696
private boolean allowUnknownMessageFields = false;
9797
private String beginString;
98+
private String fullVersion;
99+
private String majorVersion;
100+
private int minorVersion;
101+
private int extensionPack;
102+
private int servicePack;
98103
private final Map<String, Set<Integer>> messageFields = new HashMap<>();
99104
private final Map<String, Set<Integer>> requiredFields = new HashMap<>();
100105
private final Set<String> messages = new HashSet<>();
@@ -171,14 +176,57 @@ private void setVersion(String beginString) {
171176
}
172177

173178
/**
174-
* Get the FIX version associated with this dictionary.
175-
*
179+
* Get the FIX major/minor version associated with this dictionary.
180+
* E.g. FIX.5.0
176181
* @return the FIX version
177182
*/
178183
public String getVersion() {
179184
return beginString;
180185
}
181186

187+
private void setFullVersion(String fullVersion) {
188+
this.fullVersion = fullVersion;
189+
}
190+
191+
/**
192+
* Get the FIX major/minor/SP/EP version associated with this dictionary.
193+
* E.g. FIX.5.0.SP2_EP260
194+
* @return the full FIX version
195+
*/
196+
public String getFullVersion() {
197+
return fullVersion;
198+
}
199+
200+
/**
201+
* @return the ExtensionPack (EP), 0 if it is undefined.
202+
*/
203+
public int getExtensionPack() {
204+
return extensionPack;
205+
}
206+
207+
/**
208+
* @return the ServicePack (SP), 0 if it is undefined.
209+
*/
210+
public int getServicePack() {
211+
return servicePack;
212+
}
213+
214+
/**
215+
* @return the minor FIX version, 0 if it is undefined.
216+
*/
217+
public int getMinorVersion() {
218+
return minorVersion;
219+
}
220+
221+
/**
222+
* NOTE: this is of type String to cover the "Latest" case.
223+
*
224+
* @return the major FIX version
225+
*/
226+
public String getMajorVersion() {
227+
return majorVersion;
228+
}
229+
182230
private void addField(int field) {
183231
fields.add(field);
184232
}
@@ -568,6 +616,11 @@ public void setAllowUnknownMessageFields(boolean allowUnknownFields) {
568616
private void copyFrom(DataDictionary rhs) {
569617
hasVersion = rhs.hasVersion;
570618
beginString = rhs.beginString;
619+
fullVersion = rhs.fullVersion;
620+
majorVersion = rhs.majorVersion;
621+
minorVersion = rhs.minorVersion;
622+
extensionPack = rhs.extensionPack;
623+
servicePack = rhs.servicePack;
571624

572625
copyMap(messageFields, rhs.messageFields);
573626
copyMap(requiredFields, rhs.requiredFields);
@@ -939,16 +992,35 @@ private void load(InputStream inputStream, DocumentBuilderFactory factory) throw
939992
throw new ConfigError("major attribute not found on <fix>");
940993
}
941994

942-
if (!documentElement.hasAttribute("minor")) {
943-
throw new ConfigError("minor attribute not found on <fix>");
944-
}
995+
majorVersion = documentElement.getAttribute("major");
996+
minorVersion = getIntegerAttributeIfDefined(documentElement, "minor");
997+
servicePack = getIntegerAttributeIfDefined(documentElement, "servicepack");
998+
extensionPack = getIntegerAttributeIfDefined(documentElement, "extensionpack");
945999

9461000
final String dictionaryType = documentElement.hasAttribute("type") ? documentElement
9471001
.getAttribute("type") : FIX_PREFIX;
9481002

949-
setVersion(dictionaryType + "." + documentElement.getAttribute("major") + "."
950-
+ documentElement.getAttribute("minor"));
951-
1003+
if (FixVersions.LATEST.equals(majorVersion)) {
1004+
String version = dictionaryType + "." + majorVersion;
1005+
setVersion(version);
1006+
String fullVersion = version;
1007+
if (extensionPack > 0) {
1008+
fullVersion = fullVersion + "_EP" + extensionPack;
1009+
}
1010+
setFullVersion(fullVersion);
1011+
} else {
1012+
String version = dictionaryType + "." + majorVersion + "." + minorVersion;
1013+
setVersion(version);
1014+
String fullVersion = version;
1015+
if (servicePack > 0) {
1016+
fullVersion = fullVersion + "SP" + servicePack;
1017+
}
1018+
if (extensionPack > 0) {
1019+
fullVersion = fullVersion + "_EP" + extensionPack;
1020+
}
1021+
setFullVersion(fullVersion);
1022+
}
1023+
9521024
// Index Components
9531025
final NodeList componentsNode = documentElement.getElementsByTagName("components");
9541026
if (componentsNode.getLength() > 0) {
@@ -1082,6 +1154,15 @@ private void load(InputStream inputStream, DocumentBuilderFactory factory) throw
10821154
calculateOrderedFields();
10831155
}
10841156

1157+
private int getIntegerAttributeIfDefined(final Element documentElement, final String attribute) throws ConfigError {
1158+
try {
1159+
return documentElement.hasAttribute(attribute)
1160+
? Integer.valueOf(documentElement.getAttribute(attribute)) : 0;
1161+
} catch (NumberFormatException e) {
1162+
throw new ConfigError("Attribute " + attribute + " could not be parsed as Integer.", e);
1163+
}
1164+
}
1165+
10851166
public int getNumMessageCategories() {
10861167
return messageCategory.size();
10871168
}

quickfixj-core/src/main/java/quickfix/FixVersions.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@ public interface FixVersions {
2929
String BEGINSTRING_FIX43 = "FIX.4.3";
3030
String BEGINSTRING_FIX44 = "FIX.4.4";
3131

32-
/**
33-
* FIX 5.0 does not have a begin string.
32+
/*
33+
* FIX 5.0+ does not have a begin string.
3434
*/
3535
String FIX50 = "FIX.5.0";
3636
String FIX50SP1 = "FIX.5.0SP1";
3737
String FIX50SP2 = "FIX.5.0SP2";
38+
39+
String LATEST = "Latest";
40+
String FIXLATEST = "FIX." + LATEST;
3841

3942
// FIXT.x.x support
4043

quickfixj-core/src/test/java/quickfix/DataDictionaryTest.java

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,7 @@ protected void execute() throws Throwable {
794794
// If bodyOnly is true, the correct data dictionary is not checked.
795795
dd.validate(newSingle, true);
796796
}
797-
797+
798798
// QF C++ treats the string argument as a filename although it's
799799
// named 'url'. QFJ string argument can be either but this test
800800
// ensures the DD works correctly with a regular file path.
@@ -1412,6 +1412,87 @@ public void shouldFailToLoadDictionaryWhenExternalDTDisDisabled() {
14121412
assertEquals("External DTD: Failed to read external DTD 'mathml.dtd', because 'http' access is not allowed due to restriction set by the accessExternalDTD property.", e.getCause().getCause().getMessage());
14131413
}
14141414
}
1415+
1416+
/**
1417+
* For FIX.Latest a minor version is not required.
1418+
*/
1419+
@Test
1420+
public void testMissingMinorVersion() throws Exception {
1421+
String data = "";
1422+
data += "<fix major=\"5\">";
1423+
data = getCommonDataDictionaryString(data);
1424+
1425+
DataDictionary dataDictionary = new DataDictionary(new ByteArrayInputStream(data.getBytes()));
1426+
assertEquals(0, dataDictionary.getMinorVersion());
1427+
}
1428+
1429+
@Test
1430+
public void testFixLatestMajorVersion() throws Exception {
1431+
String data = "";
1432+
data += "<fix major=\"Latest\">";
1433+
data = getCommonDataDictionaryString(data);
1434+
1435+
DataDictionary dataDictionary = new DataDictionary(new ByteArrayInputStream(data.getBytes()));
1436+
assertEquals(0, dataDictionary.getMinorVersion());
1437+
assertEquals("FIX.Latest", dataDictionary.getFullVersion());
1438+
}
1439+
1440+
@Test
1441+
public void testFixLatestMajorVersionAndEP() throws Exception {
1442+
String data = "";
1443+
data += "<fix major=\"Latest\" extensionpack=\"260\">";
1444+
data = getCommonDataDictionaryString(data);
1445+
1446+
DataDictionary dataDictionary = new DataDictionary(new ByteArrayInputStream(data.getBytes()));
1447+
assertEquals(0, dataDictionary.getMinorVersion());
1448+
assertEquals("FIX.Latest_EP260", dataDictionary.getFullVersion());
1449+
}
1450+
1451+
@Test
1452+
public void testSP() throws Exception {
1453+
String data = "";
1454+
data += "<fix major=\"5\" minor=\"0\" servicepack=\"2\">";
1455+
data = getCommonDataDictionaryString(data);
1456+
1457+
DataDictionary dataDictionary = new DataDictionary(new ByteArrayInputStream(data.getBytes()));
1458+
assertEquals(0, dataDictionary.getMinorVersion());
1459+
assertEquals("FIX.5.0", dataDictionary.getVersion());
1460+
assertEquals("FIX.5.0SP2", dataDictionary.getFullVersion());
1461+
}
1462+
1463+
@Test
1464+
public void testEPAndSP() throws Exception {
1465+
String data = "";
1466+
data += "<fix major=\"5\" minor=\"0\" extensionpack=\"260\" servicepack=\"2\">";
1467+
data = getCommonDataDictionaryString(data);
1468+
1469+
DataDictionary dataDictionary = new DataDictionary(new ByteArrayInputStream(data.getBytes()));
1470+
assertEquals(0, dataDictionary.getMinorVersion());
1471+
assertEquals("FIX.5.0", dataDictionary.getVersion());
1472+
assertEquals("FIX.5.0SP2_EP260", dataDictionary.getFullVersion());
1473+
}
1474+
1475+
private String getCommonDataDictionaryString(String data) {
1476+
data += " <header>";
1477+
data += " <field name=\"BeginString\" required=\"Y\"/>";
1478+
data += " </header>";
1479+
data += " <trailer>";
1480+
data += " <field name=\"CheckSum\" required=\"Y\"/>";
1481+
data += " </trailer>";
1482+
data += " <fields>";
1483+
data += " <field number=\"8\" name=\"BeginString\" type=\"STRING\"/>";
1484+
data += " <field number=\"10\" name=\"CheckSum\" type=\"STRING\"/>";
1485+
data += " <field number=\"112\" name=\"TestReqID\" type=\"STRING\"/>";
1486+
data += " </fields>";
1487+
data += " <messages>";
1488+
data += " <message name=\"Heartbeat\" msgtype=\"0\" msgcat=\"admin\">";
1489+
data += " <field name=\"TestReqID\" required=\"N\"/>";
1490+
data += " </message>";
1491+
data += " </messages>";
1492+
data += "</fix>";
1493+
return data;
1494+
}
1495+
14151496

14161497
//
14171498
// Group Validation Tests in RepeatingGroupTest

0 commit comments

Comments
 (0)