Skip to content

Commit c85b8fb

Browse files
zyulyaevNikita Zyulyaev
authored and
Nikita Zyulyaev
committed
[Java] Using sinceVersion from field instead of type declaration
1 parent fee2a49 commit c85b8fb

File tree

3 files changed

+186
-122
lines changed

3 files changed

+186
-122
lines changed

sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/java/JavaGenerator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2410,7 +2410,7 @@ private CharSequence generateEnumDecoder(
24102410
indent + " }\n\n",
24112411
enumName,
24122412
propertyName,
2413-
generatePropertyNotPresentCondition(inComposite, DECODER, token.version(), indent),
2413+
generatePropertyNotPresentCondition(inComposite, DECODER, signalToken.version(), indent),
24142414
enumName,
24152415
generateGet(encoding.primitiveType(), "offset + " + token.offset(), byteOrderString(encoding)));
24162416
}
@@ -2468,7 +2468,7 @@ private CharSequence generateBitSetProperty(
24682468
generateFlyweightPropertyJavadoc(indent + INDENT, propertyToken, bitSetName),
24692469
bitSetName,
24702470
propertyName,
2471-
generatePropertyNotPresentCondition(inComposite, codecType, bitsetToken.version(), indent),
2471+
generatePropertyNotPresentCondition(inComposite, codecType, propertyToken.version(), indent),
24722472
propertyName,
24732473
bitsetToken.offset(),
24742474
propertyName));

sbe-tool/src/test/java/uk/co/real_logic/sbe/generation/java/SchemaExtensionTest.java

Lines changed: 165 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -64,118 +64,174 @@ public void setup() throws Exception
6464
public void testMessage1() throws Exception
6565
{
6666
final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]);
67-
final Object encoder = wrap(buffer, compile("TestMessage1Encoder").newInstance());
68-
69-
set(encoder, "tag1", int.class, 100);
70-
set(encoder, "tag2", int.class, 200);
71-
72-
final Object compositeEncoder = getACompositeEncoder(buffer, 8);
73-
wrap(8, compositeEncoder, buffer, BUFFER_CLASS);
74-
75-
set(compositeEncoder, "value", int.class, 300);
76-
77-
final Object decoderVersion0 = getMessage1Decoder(buffer, 4, 0);
78-
assertEquals(100, get(decoderVersion0, "tag1"));
79-
assertEquals(Integer.MIN_VALUE, get(decoderVersion0, "tag2"));
80-
assertNull(get(decoderVersion0, "tag3"));
81-
82-
assertEquals(0, decoderVersion0.getClass().getMethod("tag1SinceVersion").invoke(null));
83-
assertEquals(1, decoderVersion0.getClass().getMethod("tag2SinceVersion").invoke(null));
84-
assertEquals(3, decoderVersion0.getClass().getMethod("tag3SinceVersion").invoke(null));
85-
86-
final Object decoderVersion1 = getMessage1Decoder(buffer, 8, 1);
87-
assertEquals(100, get(decoderVersion1, "tag1"));
88-
assertEquals(200, get(decoderVersion1, "tag2"));
89-
assertNull(get(decoderVersion1, "tag3"));
90-
91-
final Object decoderVersion2 = getMessage1Decoder(buffer, 8, 2);
92-
assertEquals(100, get(decoderVersion2, "tag1"));
93-
assertEquals(200, get(decoderVersion2, "tag2"));
94-
assertNull(get(decoderVersion1, "tag3"));
95-
96-
final Object decoderVersion3 = getMessage1Decoder(buffer, 12, 3);
97-
assertEquals(100, get(decoderVersion3, "tag1"));
98-
assertEquals(200, get(decoderVersion3, "tag2"));
99-
final Object compositeDecoder3 = get(decoderVersion3, "tag3");
100-
assertNotNull(compositeDecoder3);
101-
assertEquals(300, get(compositeDecoder3, "value"));
102-
103-
final Object decoderVersion4 = getMessage1Decoder(buffer, 12, 4);
104-
assertEquals(100, get(decoderVersion4, "tag1"));
105-
assertEquals(200, get(decoderVersion4, "tag2"));
106-
final Object compositeDecoder4 = get(decoderVersion4, "tag3");
107-
assertNotNull(compositeDecoder4);
108-
assertEquals(300, get(compositeDecoder4, "value"));
67+
68+
{ // Encode
69+
final Object encoder = wrap(buffer, compile("TestMessage1Encoder").newInstance());
70+
71+
set(encoder, "tag1", int.class, 100);
72+
set(encoder, "tag2", int.class, 200);
73+
74+
final Object compositeEncoder = encoder.getClass().getMethod("tag3").invoke(encoder);
75+
set(compositeEncoder, "value", int.class, 300);
76+
77+
final Object enumConstant = getAEnumConstant(encoder, "AEnum", 1);
78+
set(encoder, "tag4", enumConstant.getClass(), enumConstant);
79+
80+
final Object setEncoder = encoder.getClass().getMethod("tag5").invoke(encoder);
81+
set(setEncoder, "firstChoice", boolean.class, false);
82+
set(setEncoder, "secondChoice", boolean.class, true);
83+
}
84+
85+
{ // Decode version 0
86+
final Object decoderVersion0 = getMessage1Decoder(buffer, 4, 0);
87+
assertEquals(100, get(decoderVersion0, "tag1"));
88+
assertEquals(Integer.MIN_VALUE, get(decoderVersion0, "tag2"));
89+
assertNull(get(decoderVersion0, "tag3"));
90+
assertNull(get(decoderVersion0, "tag4"));
91+
assertNull(get(decoderVersion0, "tag5"));
92+
93+
assertEquals(0, decoderVersion0.getClass().getMethod("tag1SinceVersion").invoke(null));
94+
assertEquals(1, decoderVersion0.getClass().getMethod("tag2SinceVersion").invoke(null));
95+
assertEquals(2, decoderVersion0.getClass().getMethod("tag3SinceVersion").invoke(null));
96+
assertEquals(3, decoderVersion0.getClass().getMethod("tag4SinceVersion").invoke(null));
97+
assertEquals(4, decoderVersion0.getClass().getMethod("tag5SinceVersion").invoke(null));
98+
}
99+
100+
{ // Decode version 1
101+
final Object decoderVersion1 = getMessage1Decoder(buffer, 8, 1);
102+
assertEquals(100, get(decoderVersion1, "tag1"));
103+
assertEquals(200, get(decoderVersion1, "tag2"));
104+
assertNull(get(decoderVersion1, "tag3"));
105+
assertNull(get(decoderVersion1, "tag4"));
106+
assertNull(get(decoderVersion1, "tag5"));
107+
}
108+
109+
{ // Decode version 2
110+
final Object decoderVersion2 = getMessage1Decoder(buffer, 8, 2);
111+
assertEquals(100, get(decoderVersion2, "tag1"));
112+
assertEquals(200, get(decoderVersion2, "tag2"));
113+
final Object compositeDecoder2 = get(decoderVersion2, "tag3");
114+
assertNotNull(compositeDecoder2);
115+
assertEquals(300, get(compositeDecoder2, "value"));
116+
assertNull(get(decoderVersion2, "tag4"));
117+
assertNull(get(decoderVersion2, "tag5"));
118+
}
119+
120+
{ // Decode version 3
121+
final Object decoderVersion3 = getMessage1Decoder(buffer, 12, 3);
122+
assertEquals(100, get(decoderVersion3, "tag1"));
123+
assertEquals(200, get(decoderVersion3, "tag2"));
124+
final Object compositeDecoder3 = get(decoderVersion3, "tag3");
125+
assertNotNull(compositeDecoder3);
126+
assertEquals(300, get(compositeDecoder3, "value"));
127+
final Object enumConstant = getAEnumConstant(decoderVersion3, "AEnum", 1);
128+
assertEquals(enumConstant, get(decoderVersion3, "tag4"));
129+
assertNull(get(decoderVersion3, "tag5"));
130+
}
131+
132+
{ // Decode version 4
133+
final Object decoderVersion4 = getMessage1Decoder(buffer, 12, 4);
134+
assertEquals(100, get(decoderVersion4, "tag1"));
135+
assertEquals(200, get(decoderVersion4, "tag2"));
136+
final Object compositeDecoder4 = get(decoderVersion4, "tag3");
137+
assertNotNull(compositeDecoder4);
138+
assertEquals(300, get(compositeDecoder4, "value"));
139+
final Object enumConstant = getAEnumConstant(decoderVersion4, "AEnum", 1);
140+
assertEquals(enumConstant, get(decoderVersion4, "tag4"));
141+
final Object setDecoder = get(decoderVersion4, "tag5");
142+
assertNotNull(setDecoder);
143+
assertEquals(false, get(setDecoder, "firstChoice"));
144+
assertEquals(true, get(setDecoder, "secondChoice"));
145+
}
109146
}
110147

111148
@Test
112149
public void testMessage2() throws Exception
113150
{
114151
final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]);
115-
final Object encoder = wrap(buffer, compile("TestMessage2Encoder").newInstance());
116-
117-
set(encoder, "tag1", int.class, 100);
118-
set(encoder, "tag2", int.class, 200);
119-
120-
final Object compositeEncoder = getACompositeEncoder(buffer, 8);
121-
set(compositeEncoder, "value", int.class, 300);
122-
123-
final Object decoderVersion0 = getMessage2Decoder(buffer, 4, 0);
124-
assertEquals(100, get(decoderVersion0, "tag1"));
125-
assertEquals(Integer.MIN_VALUE, get(decoderVersion0, "tag2"));
126-
assertNull(get(decoderVersion0, "tag3"));
127-
128-
assertEquals(0, decoderVersion0.getClass().getMethod("tag1SinceVersion").invoke(null));
129-
assertEquals(2, decoderVersion0.getClass().getMethod("tag2SinceVersion").invoke(null));
130-
assertEquals(4, decoderVersion0.getClass().getMethod("tag3SinceVersion").invoke(null));
131-
132-
final Object decoderVersion1 = getMessage2Decoder(buffer, 4, 1);
133-
assertEquals(100, get(decoderVersion1, "tag1"));
134-
assertEquals(Integer.MIN_VALUE, get(decoderVersion1, "tag2"));
135-
assertNull(get(decoderVersion1, "tag3"));
136-
137-
final Object decoderVersion2 = getMessage2Decoder(buffer, 8, 2);
138-
assertEquals(100, get(decoderVersion2, "tag1"));
139-
assertEquals(200, get(decoderVersion2, "tag2"));
140-
assertNull(get(decoderVersion1, "tag3"));
141-
142-
final Object decoderVersion3 = getMessage2Decoder(buffer, 8, 3);
143-
assertEquals(100, get(decoderVersion3, "tag1"));
144-
assertEquals(200, get(decoderVersion3, "tag2"));
145-
assertNull(get(decoderVersion1, "tag3"));
146-
147-
final Object decoderVersion4 = getMessage2Decoder(buffer, 12, 4);
148-
assertEquals(100, get(decoderVersion4, "tag1"));
149-
assertEquals(200, get(decoderVersion4, "tag2"));
150-
final Object compositeDecoder4 = get(decoderVersion4, "tag3");
151-
assertNotNull(compositeDecoder4);
152-
assertEquals(300, get(compositeDecoder4, "value"));
153-
}
154152

155-
@Test
156-
public void testMessageHeader() throws Exception
157-
{
158-
final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]);
159-
final Object encoder = wrap(buffer, compile("MessageHeaderEncoder").newInstance());
160-
161-
set(encoder, "blockLength", int.class, 10);
162-
set(encoder, "templateId", int.class, 1);
163-
set(encoder, "schemaId", int.class, 1);
164-
set(encoder, "version", int.class, 5);
165-
set(encoder, "headerLength", int.class, 12);
166-
set(encoder, "extraField", int.class, 100);
167-
168-
final Object decoder = compile("MessageHeaderDecoder").newInstance();
169-
wrap(0, decoder, buffer, READ_ONLY_BUFFER_CLASS);
170-
171-
assertEquals(10, get(decoder, "blockLength"));
172-
assertEquals(1, get(decoder, "templateId"));
173-
assertEquals(1, get(decoder, "schemaId"));
174-
assertEquals(5, get(decoder, "version"));
175-
assertEquals(12, get(decoder, "headerLength"));
176-
assertEquals(100, get(decoder, "extraField"));
177-
178-
assertEquals(5, decoder.getClass().getMethod("extraFieldSinceVersion").invoke(null));
153+
{ // Encode
154+
final Object encoder = wrap(buffer, compile("TestMessage2Encoder").newInstance());
155+
156+
set(encoder, "tag1", int.class, 100);
157+
set(encoder, "tag2", int.class, 200);
158+
159+
final Object compositeEncoder = encoder.getClass().getMethod("tag3").invoke(encoder);
160+
set(compositeEncoder, "value", int.class, 300);
161+
162+
final Object enumConstant = getAEnumConstant(encoder, "AEnum", 1);
163+
set(encoder, "tag4", enumConstant.getClass(), enumConstant);
164+
165+
final Object setEncoder = encoder.getClass().getMethod("tag5").invoke(encoder);
166+
set(setEncoder, "firstChoice", boolean.class, false);
167+
set(setEncoder, "secondChoice", boolean.class, true);
168+
}
169+
170+
{ // Decode version 0
171+
final Object decoderVersion0 = getMessage2Decoder(buffer, 4, 0);
172+
assertEquals(100, get(decoderVersion0, "tag1"));
173+
assertEquals(Integer.MIN_VALUE, get(decoderVersion0, "tag2"));
174+
assertNull(get(decoderVersion0, "tag3"));
175+
assertNull(get(decoderVersion0, "tag4"));
176+
assertNull(get(decoderVersion0, "tag5"));
177+
178+
assertEquals(0, decoderVersion0.getClass().getMethod("tag1SinceVersion").invoke(null));
179+
assertEquals(2, decoderVersion0.getClass().getMethod("tag2SinceVersion").invoke(null));
180+
assertEquals(1, decoderVersion0.getClass().getMethod("tag3SinceVersion").invoke(null));
181+
assertEquals(4, decoderVersion0.getClass().getMethod("tag4SinceVersion").invoke(null));
182+
assertEquals(3, decoderVersion0.getClass().getMethod("tag5SinceVersion").invoke(null));
183+
}
184+
185+
{ // Decode version 1
186+
final Object decoderVersion1 = getMessage2Decoder(buffer, 8, 1);
187+
assertEquals(100, get(decoderVersion1, "tag1"));
188+
assertEquals(Integer.MIN_VALUE, get(decoderVersion1, "tag2"));
189+
final Object compositeDecoder2 = get(decoderVersion1, "tag3");
190+
assertNotNull(compositeDecoder2);
191+
assertEquals(300, get(compositeDecoder2, "value"));
192+
assertNull(get(decoderVersion1, "tag4"));
193+
assertNull(get(decoderVersion1, "tag5"));
194+
}
195+
196+
{ // Decode version 2
197+
final Object decoderVersion2 = getMessage2Decoder(buffer, 8, 2);
198+
assertEquals(100, get(decoderVersion2, "tag1"));
199+
assertEquals(200, get(decoderVersion2, "tag2"));
200+
final Object compositeDecoder2 = get(decoderVersion2, "tag3");
201+
assertNotNull(compositeDecoder2);
202+
assertEquals(300, get(compositeDecoder2, "value"));
203+
assertNull(get(decoderVersion2, "tag4"));
204+
assertNull(get(decoderVersion2, "tag5"));
205+
}
206+
207+
{ // Decode version 3
208+
final Object decoderVersion3 = getMessage2Decoder(buffer, 12, 3);
209+
assertEquals(100, get(decoderVersion3, "tag1"));
210+
assertEquals(200, get(decoderVersion3, "tag2"));
211+
final Object compositeDecoder3 = get(decoderVersion3, "tag3");
212+
assertNotNull(compositeDecoder3);
213+
assertEquals(300, get(compositeDecoder3, "value"));
214+
assertNull(get(decoderVersion3, "tag4"));
215+
final Object setDecoder = get(decoderVersion3, "tag5");
216+
assertNotNull(setDecoder);
217+
assertEquals(false, get(setDecoder, "firstChoice"));
218+
assertEquals(true, get(setDecoder, "secondChoice"));
219+
}
220+
221+
{ // Decode version 4
222+
final Object decoderVersion4 = getMessage2Decoder(buffer, 12, 4);
223+
assertEquals(100, get(decoderVersion4, "tag1"));
224+
assertEquals(200, get(decoderVersion4, "tag2"));
225+
final Object compositeDecoder4 = get(decoderVersion4, "tag3");
226+
assertNotNull(compositeDecoder4);
227+
assertEquals(300, get(compositeDecoder4, "value"));
228+
final Object enumConstant = getAEnumConstant(decoderVersion4, "AEnum", 1);
229+
assertEquals(enumConstant, get(decoderVersion4, "tag4"));
230+
final Object setDecoder = get(decoderVersion4, "tag5");
231+
assertNotNull(setDecoder);
232+
assertEquals(false, get(setDecoder, "firstChoice"));
233+
assertEquals(true, get(setDecoder, "secondChoice"));
234+
}
179235
}
180236

181237
private JavaGenerator generator()
@@ -197,11 +253,11 @@ private Object getMessage2Decoder(final UnsafeBuffer buffer, final int blockLeng
197253
return wrap(buffer, decoder, blockLength, version);
198254
}
199255

200-
private Object getACompositeEncoder(final UnsafeBuffer buffer, final int offset) throws Exception
256+
private Object getAEnumConstant(
257+
final Object flyweight, final String enumClassName, final int constantIndex) throws Exception
201258
{
202-
final Object encoder = compile("ACompositeEncoder").newInstance();
203-
wrap(offset, encoder, buffer, BUFFER_CLASS);
204-
return encoder;
259+
final String fqClassName = ir.applicableNamespace() + "." + enumClassName;
260+
return flyweight.getClass().getClassLoader().loadClass(fqClassName).getEnumConstants()[constantIndex];
205261
}
206262

207263
private Class<?> compile(final String className) throws Exception

sbe-tool/src/test/resources/extension-schema.xml

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,43 @@
1010
<type name="templateId" primitiveType="uint16"/>
1111
<type name="schemaId" primitiveType="uint16"/>
1212
<type name="version" primitiveType="uint16"/>
13-
<type name="headerLength" primitiveType="uint16"/>
14-
15-
<type name="extraField" primitiveType="int32" sinceVersion="5"/>
1613
</composite>
1714
<composite name="groupSizeEncoding" description="Repeating group dimensions">
1815
<type name="blockLength" primitiveType="uint16"/>
1916
<type name="numInGroup" primitiveType="uint8" semanticType="NumInGroup"/>
2017
</composite>
2118
<type name="AType" primitiveType="int32" sinceVersion="1"/>
22-
<composite name="AComposite" sinceVersion="3">
19+
<composite name="AComposite" sinceVersion="1">
2320
<type name="value" primitiveType="int32"/>
2421
</composite>
22+
<enum name="AEnum" encodingType="uint8" sinceVersion="3">
23+
<validValue name="FirstValue">0</validValue>
24+
<validValue name="SecondValue">1</validValue>
25+
</enum>
26+
<set name="ASet" encodingType="uint8" sinceVersion="3">
27+
<choice name="FirstChoice">0</choice>
28+
<choice name="SecondChoice">1</choice>
29+
</set>
2530
</types>
2631
<!--
2732
Version 0: schema created
28-
Version 1: aType introduced and tag2 added to TestMessage1
29-
Version 2: tag2 added to TestMessage2
30-
Version 3: aComposite introduced and tag3 added to TestMessage1
31-
Version 4: tag3 added to TestMessage2
32-
Version 5: extraField is added to messageHeader
33+
Version 1: AType, AComposite introduced; tag2 added to TestMessage1, tag3 added to TestMessage2
34+
Version 2: tag3 added to TestMessage1, tag2 added to TestMessage2
35+
Version 3: AEnum, ASet introduced; tag4 added to TestMessage1, tag5 added to TestMessage2
36+
Version 4: tag5 added to TestMessage1, tag4 added to TestMessage2
3337
-->
3438
<sbe:message name="TestMessage1" id="1">
3539
<field name="tag1" id="1" type="int32"/>
3640
<field name="tag2" id="2" type="AType" sinceVersion="1"/>
37-
<field name="tag3" id="3" type="AComposite" sinceVersion="3"/>
41+
<field name="tag3" id="3" type="AComposite" sinceVersion="2"/>
42+
<field name="tag4" id="4" type="AEnum" sinceVersion="3"/>
43+
<field name="tag5" id="5" type="ASet" sinceVersion="4"/>
3844
</sbe:message>
3945
<sbe:message name="TestMessage2" id="2">
4046
<field name="tag1" id="1" type="int32"/>
47+
<field name="tag3" id="3" type="AComposite" sinceVersion="1"/>
4148
<field name="tag2" id="2" type="AType" sinceVersion="2"/>
42-
<field name="tag3" id="3" type="AComposite" sinceVersion="4"/>
49+
<field name="tag5" id="5" type="ASet" sinceVersion="3"/>
50+
<field name="tag4" id="4" type="AEnum" sinceVersion="4"/>
4351
</sbe:message>
4452
</sbe:messageSchema>

0 commit comments

Comments
 (0)