Skip to content

Commit d0d5f64

Browse files
author
Dan Geabunea
committed
Released version 0.9.30; Custom decoding/encoding implementations can be attached to the Aserix decoder object for any given category;
1 parent 2a24b98 commit d0d5f64

File tree

10 files changed

+200
-11
lines changed

10 files changed

+200
-11
lines changed

README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ for (AsterixDataBlock asterixDataBlock : dataBlocks) {
5959
}
6060
```
6161

62-
## How to implement a custom Reserved Field
62+
## How to implement a custom Reserved Field (SP,RE) for an Asterix Category
63+
64+
In order to keep this library flexible, custom implementations for RE and SP fields can be
65+
attached to the Asterix Decoder object in your own code.
6366

6467
In order to implement a custom reserved AsterixField, you first need to create
6568
a new class and inherit ReservedAsterixField. Then, you have to add implementations
@@ -98,9 +101,14 @@ public class SomeCustomAsterixFieldFactory implements ReservedFieldFactory {
98101
}
99102
```
100103

101-
Finally, we have to attach the custom factory to our Cat062Record.
104+
Finally, we have to attach the custom factory to the Asterix Decoder using the attachCustomReservedFieldFactory method.
105+
The custom factory shall be attached to a given category. This way, different factories can be assigned
106+
to various categories.
102107

103108
```java
104-
ReservedFieldFactory customFieldFactory = new SomeCustomAsterixFieldFactory();
105-
Cat062Record cat062Record = new Cat062Record(customFieldFactory);
109+
AsterixDecoder decoder = new AsterixDecoder(62);
110+
decoder.attachCustomReservedFieldFactory(62, new SomeCustomAsterixFieldFactory());
111+
...
112+
List<AsterixDataBlock> dataBlocks = asterixDecoder.decode(...);
113+
106114
```

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<groupId>jlg-consulting</groupId>
77
<artifactId>jade</artifactId>
8-
<version>0.9.26</version>
8+
<version>0.9.30</version>
99
<packaging>jar</packaging>
1010

1111
<name>jade</name>

src/main/java/jlg/jade/asterix/AsterixDataBlock.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import jlg.jade.common.DebugMessageSource;
1010
import jlg.jade.common.Decodable;
11+
import org.springframework.util.Assert;
1112
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
1213

1314
import java.util.ArrayList;
@@ -22,10 +23,30 @@
2223
public class AsterixDataBlock extends DebugMessageSource implements Decodable {
2324
private final int category;
2425
private final List<AsterixRecord> records;
26+
private ReservedFieldFactory customReservedFieldFactory;
2527

28+
/**
29+
* Create an Asterix data block for the specified category
30+
* @param category
31+
*/
2632
public AsterixDataBlock(int category) {
2733
this.category = category;
2834
this.records = new ArrayList<>();
35+
this.customReservedFieldFactory = null;
36+
}
37+
38+
/**
39+
* Create an Asterix data block for the specified category with a custom factory
40+
* implementation for SP,RE fields.
41+
* @param category
42+
* @param reservedFieldFactory The custom reserved field factory
43+
*/
44+
public AsterixDataBlock(int category, ReservedFieldFactory reservedFieldFactory) {
45+
Assert.notNull(reservedFieldFactory);
46+
47+
this.category = category;
48+
this.records = new ArrayList<>();
49+
this.customReservedFieldFactory = reservedFieldFactory;
2950
}
3051

3152
/**
@@ -39,7 +60,7 @@ public AsterixDataBlock(int category) {
3960
*/
4061
public int decode(byte[] input, int offset, int length) {
4162
while (offset < length) {
42-
AsterixRecord record = new StandardAsterixRecord(category);
63+
AsterixRecord record = buildAsterixRecord(category, customReservedFieldFactory);
4364

4465
offset = record.decode(input, offset, length);
4566

@@ -85,6 +106,7 @@ public int decode(byte[] input, int offset, int length) {
85106
return offset;
86107
}
87108

109+
88110
/**
89111
* Encodes the current Asterix data block into a byte array, that can be then sent over the
90112
* network
@@ -108,4 +130,21 @@ public int getCategory() {
108130
public List<AsterixRecord> getRecords() {
109131
return records;
110132
}
133+
134+
/**
135+
* Build an Asterix record, by calling the appropriate constructor.
136+
*
137+
* @param category
138+
* @param customReservedFieldFactory
139+
* @return
140+
*/
141+
private AsterixRecord buildAsterixRecord(int category, ReservedFieldFactory customReservedFieldFactory) {
142+
AsterixRecord record;
143+
if (customReservedFieldFactory == null) {
144+
record = new StandardAsterixRecord(category);
145+
} else {
146+
record = new StandardAsterixRecord(category, customReservedFieldFactory);
147+
}
148+
return record;
149+
}
111150
}

src/main/java/jlg/jade/asterix/AsterixDecoder.java

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
*/
77
package jlg.jade.asterix;
88

9+
import org.springframework.util.Assert;
10+
911
import java.util.ArrayList;
1012
import java.util.HashMap;
1113
import java.util.List;
@@ -19,6 +21,7 @@
1921
public class AsterixDecoder {
2022
private final HashMap<Integer, Boolean> allowedCategories;
2123
private final HashMap<Integer, Integer> nbOfDataBlocks;
24+
private final HashMap<Integer, ReservedFieldFactory> customReservedFieldFactories;
2225

2326
private AsterixDecoder() {
2427
allowedCategories = new HashMap<>();
@@ -36,6 +39,8 @@ private AsterixDecoder() {
3639
nbOfDataBlocks.put(62, 0);
3740
nbOfDataBlocks.put(65, 0);
3841
nbOfDataBlocks.put(150, 0);
42+
43+
customReservedFieldFactories = new HashMap<>();
3944
}
4045

4146
public AsterixDecoder(int... categoriesToDecode) {
@@ -70,8 +75,9 @@ public AsterixDecoder(String categoriesToDecode) {
7075
}
7176

7277
public AsterixDecoder(List<Integer> categoriesToDecode) {
73-
allowedCategories = new HashMap<>();
74-
nbOfDataBlocks = new HashMap<>();
78+
this();
79+
allowedCategories.clear();
80+
nbOfDataBlocks.clear();
7581
for (int category : categoriesToDecode) {
7682
allowedCategories.put(category, true);
7783
nbOfDataBlocks.put(category, 0);
@@ -97,7 +103,11 @@ public List<AsterixDataBlock> decode(byte[] input, int offset, int length) {
97103

98104
Boolean shouldDecodeCategory = allowedCategories.get(dataBlockCategory);
99105
if (shouldDecodeCategory != null && shouldDecodeCategory) {
100-
AsterixDataBlock dataBlock = new AsterixDataBlock(dataBlockCategory);
106+
107+
AsterixDataBlock dataBlock = buildAsterixDataBlock(
108+
dataBlockCategory,
109+
getCustomReservedFieldFactory(dataBlockCategory)
110+
);
101111

102112
inputIndex += 3;
103113

@@ -136,4 +146,43 @@ public HashMap<Integer, Boolean> getAllowedCategories() {
136146
public HashMap<Integer, Integer> getNbOfDataBlocks() {
137147
return nbOfDataBlocks;
138148
}
149+
150+
/**
151+
* Attach a custom reserved field implementation (decoding,encoding of SP,RE) for a given
152+
* Asterix category. If there is a factory associated with the category, the old
153+
* entry shall be replaced with the new one.
154+
*
155+
* @param category
156+
* @param reservedFieldFactory
157+
*/
158+
public void attachCustomReservedFieldFactory(int category,
159+
ReservedFieldFactory reservedFieldFactory) {
160+
Assert.notNull(reservedFieldFactory);
161+
this.customReservedFieldFactories.put(category, reservedFieldFactory);
162+
}
163+
164+
/**
165+
* Get the custom reserved field implementation factory for a given Asterix category,
166+
* if it has been attached. Will return NULL if no factory is associated with the category
167+
*
168+
* @param category
169+
* @return
170+
*/
171+
public ReservedFieldFactory getCustomReservedFieldFactory(int category) {
172+
return this.customReservedFieldFactories.get(category);
173+
}
174+
175+
private AsterixDataBlock buildAsterixDataBlock(int category, ReservedFieldFactory customReservedFieldFactory) {
176+
AsterixDataBlock dataBlock;
177+
if (customReservedFieldFactory == null) {
178+
dataBlock = new AsterixDataBlock(category);
179+
} else {
180+
dataBlock = new AsterixDataBlock(
181+
category,
182+
customReservedFieldFactory
183+
);
184+
}
185+
186+
return dataBlock;
187+
}
139188
}

src/main/java/jlg/jade/asterix/StandardAsterixRecord.java

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import jlg.jade.asterix.cat065.Cat065Record;
1414
import jlg.jade.asterix.cat150.Cat150Record;
1515
import jlg.jade.common.DebugMessageSource;
16+
import org.springframework.util.Assert;
1617
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
1718

1819
import java.util.AbstractMap;
@@ -32,14 +33,18 @@ public class StandardAsterixRecord extends DebugMessageSource implements Asterix
3233
private Cat150Record cat150Record;
3334
/**
3435
* This field is used by 3rd party applications using this library. It helps to
35-
* add more informaiton on the ASTERIX record, that can simplify the logic in
36+
* add more information on the ASTERIX record, that can simplify the logic in
3637
* their own apps.
3738
*
3839
* @implNote No ASTERIX decoded field shall be inserted here. This will be empty. Only users can
3940
* add info on this list after the decoding has been done.
4041
*/
4142
private AbstractMap<String, Object> additionalInfo;
4243

44+
/**
45+
* Create an Asterix Record without any SP,RE fields
46+
* @param category
47+
*/
4348
public StandardAsterixRecord(int category) {
4449
this.category = category;
4550
this.additionalInfo = new HashMap<>();
@@ -73,13 +78,54 @@ public StandardAsterixRecord(int category) {
7378
}
7479
}
7580

81+
/**
82+
* Create an Asterix Record where the SP or RE fields need to have a custom decoding/encoding
83+
* implementation
84+
* @param category
85+
*/
86+
public StandardAsterixRecord(int category, ReservedFieldFactory customReservedFieldFactory) {
87+
Assert.notNull(customReservedFieldFactory); //Use other constructor if no custom factory is needed
88+
89+
this.category = category;
90+
this.additionalInfo = new HashMap<>();
91+
switch (category) {
92+
case 4: {
93+
this.cat004Record = new Cat004Record(customReservedFieldFactory);
94+
break;
95+
}
96+
case 34: {
97+
this.cat034Record = new Cat034Record(customReservedFieldFactory);
98+
break;
99+
}
100+
case 48: {
101+
this.cat048Record = new Cat048Record(customReservedFieldFactory);
102+
break;
103+
}
104+
case 62: {
105+
this.cat062Record = new Cat062Record(customReservedFieldFactory);
106+
break;
107+
}
108+
case 65: {
109+
this.cat065Record = new Cat065Record(customReservedFieldFactory);
110+
break;
111+
}
112+
case 150: {
113+
//Cat150 does not have SP and RE fields, so we do not need to pass in additional arguments
114+
this.cat150Record = new Cat150Record();
115+
break;
116+
}
117+
default:
118+
throw new NotImplementedException();
119+
}
120+
}
121+
76122
/**
77123
* Decodes the raw data to Asterix data block, containing zero or more Asterix
78124
* records
79125
*
80126
* @param input The raw data
81127
* @param offset The start offset in the raw data, at which reading should begin
82-
* @param inputLength The ammount of data that nees to be read from the input
128+
* @param inputLength The amount of data that needs to be read from the input
83129
* @return The new offset in the raw data
84130
*/
85131
@Override

src/main/java/jlg/jade/asterix/cat034/Cat034Record.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ public Cat034Record() {
3232
this.reservedFieldFactory = new DefaultReservedFieldFactory();
3333
}
3434

35+
public Cat034Record(ReservedFieldFactory customReservedFieldFactory) {
36+
this.reservedFieldFactory = customReservedFieldFactory;
37+
}
38+
3539
@Override
3640
protected int setMaxFspecSizeInBytes() {
3741
return AsterixItemLength.TWO_BYTES.getValue();

src/main/java/jlg/jade/asterix/cat048/Cat048Record.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ public Cat048Record() {
4545
this.reservedFieldFactory = new DefaultReservedFieldFactory();
4646
}
4747

48+
public Cat048Record(ReservedFieldFactory customReservedFieldFactory) {
49+
this.reservedFieldFactory = customReservedFieldFactory;
50+
}
51+
4852
@Override
4953
protected String setDisplayName() {
5054
return "*** Category 048 Record ***";
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package jlg.jade.test.asterix;
2+
3+
import jlg.jade.asterix.AsterixDataBlock;
4+
import org.junit.Test;
5+
6+
/**
7+
* Created by Dan Geabunea on 1/6/2017.
8+
*/
9+
public class AsterixDataBlockTest {
10+
11+
@Test(expected = IllegalArgumentException.class)
12+
public void should_throw_if_we_pass_null_custom_reserved_field_factory_in_ctor(){
13+
AsterixDataBlock dataBlock = new AsterixDataBlock(62, null);
14+
}
15+
}

src/test/java/jlg/jade/test/asterix/AsterixDecoderTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import jlg.jade.asterix.AsterixDataBlock;
88
import jlg.jade.asterix.AsterixDecoder;
99
import jlg.jade.asterix.AsterixRecord;
10+
import jlg.jade.asterix.DefaultReservedFieldFactory;
1011
import jlg.jade.test.utils.TestHelper;
1112
import org.junit.Test;
1213

@@ -54,4 +55,11 @@ public void the_decode_method_should_decode_only_specified_categories_from_the_l
5455
// assert
5556
assertEquals("Number of decoded Cat062 items is not correct", 22396, asterixRecords.size());
5657
}
58+
59+
@Test(expected = IllegalArgumentException.class)
60+
public void attachCustomReservedFieldFactory_should_throw_if_custom_reserved_field_factory_argument_is_null(){
61+
AsterixDecoder decoder = new AsterixDecoder(62);
62+
decoder.attachCustomReservedFieldFactory(62, new DefaultReservedFieldFactory());
63+
64+
}
5765
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package jlg.jade.test.asterix;
2+
3+
import jlg.jade.asterix.AsterixRecord;
4+
import jlg.jade.asterix.StandardAsterixRecord;
5+
import org.junit.Test;
6+
7+
/**
8+
* Created by Dan Geabunea on 1/6/2017.
9+
*/
10+
public class AsterixRecordTest {
11+
12+
@Test(expected = IllegalArgumentException.class)
13+
public void should_throw_if_we_pass_null_custom_reserved_filed_factory_in_ctor(){
14+
AsterixRecord asterixRecord = new StandardAsterixRecord(62, null);
15+
}
16+
}

0 commit comments

Comments
 (0)