Skip to content

Commit f3baca4

Browse files
committed
[Java] Include removing fields from messages/groups when transforming to generate older versions.
1 parent c239921 commit f3baca4

File tree

8 files changed

+145
-49
lines changed

8 files changed

+145
-49
lines changed

sbe-tool/src/main/java/uk/co/real_logic/sbe/SbeTool.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ public class SbeTool
190190
* to generate older versions of a schema to do version compatibility testing.
191191
* <p>
192192
* This field can contain a list of ordered pairs in the form:
193-
* <code>((&lt;schema id&gt; | '*') ':' &lt;schema id&gt;)(',' ((&lt;schema id&gt; | '*') ':' &lt;schema id&gt;))*</code>.
193+
* <code>((&lt;schema id&gt; | '*') ':' &lt;schema id&gt;)(',' ((&lt;schema id&gt; | '*') ':' &lt;schema id&gt;))*
194+
* </code>.
194195
* E.g. <code>123:5,*:6</code> which means transform schema with id = 123 to version 5, all others to version 6.
195196
*/
196197
public static final String SCHEMA_TRANSFORM_VERSION = "sbe.schema.transform.version";

sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Field.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,27 @@ public class Field
8888
this.timeUnit = timeUnit;
8989
}
9090

91+
Field(final Field field, final List<Field> groupFieldList)
92+
{
93+
this(
94+
field.name,
95+
field.description,
96+
field.id,
97+
field.type,
98+
field.offset,
99+
field.semanticType,
100+
field.presence,
101+
field.valueRef,
102+
field.blockLength,
103+
field.dimensionType,
104+
field.variableLength,
105+
field.sinceVersion,
106+
field.deprecated,
107+
field.epoch,
108+
field.timeUnit);
109+
this.groupFieldList = groupFieldList;
110+
}
111+
91112
/**
92113
* Validate the node is correct for the type.
93114
*

sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/Message.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,20 @@ public Message(final Node messageNode, final Map<String, Type> typeByNameMap) th
8383
validateBlockLength(messageNode, blockLength, computedBlockLength);
8484
}
8585

86+
Message(final Message message, final List<Field> newFieldList)
87+
{
88+
id = message.id;
89+
name = message.name;
90+
description = message.description;
91+
blockLength = message.blockLength;
92+
sinceVersion = message.sinceVersion;
93+
deprecated = message.deprecated;
94+
semanticType = message.semanticType;
95+
typeByNameMap = message.typeByNameMap;
96+
fieldList = newFieldList;
97+
computedBlockLength = computeMessageRootBlockLength(newFieldList);
98+
}
99+
86100
/**
87101
* Return the template schemaId of the message
88102
*

sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,5 @@ public interface SchemaTransformer
3131
* @param originalSchema to be transformed
3232
* @return resulting transformed schema.
3333
*/
34-
MessageSchema transform(final MessageSchema originalSchema);
34+
MessageSchema transform(MessageSchema originalSchema);
3535
}

sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactory.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ public class SchemaTransformerFactory implements SchemaTransformer
2626
{
2727
private final SchemaTransformer transformer;
2828

29+
/**
30+
* Construct the SchemaTransformerFactory with the specified configuration for filtering the messages and types by
31+
* version.
32+
*
33+
* @param schemaTransformConfig configuration for the sinceVersion transformation
34+
* @see uk.co.real_logic.sbe.SbeTool#SCHEMA_TRANSFORM_VERSION
35+
*/
2936
public SchemaTransformerFactory(final String schemaTransformConfig)
3037
{
3138
transformer = parse(schemaTransformConfig);
@@ -66,7 +73,7 @@ private static void parseComponents(
6673
final String[] configuration,
6774
final Map<Integer, SchemaTransformer> transformerBySchemaId)
6875
{
69-
for (String field : configuration)
76+
for (final String field : configuration)
7077
{
7178
final String[] fieldParts = field.split(":");
7279

sbe-tool/src/main/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformer.java

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,26 @@
1515
*/
1616
package uk.co.real_logic.sbe.xml;
1717

18-
import java.util.Collection;
19-
import java.util.HashMap;
20-
import java.util.Map;
18+
import java.util.*;
2119

2220
class SinceVersionSchemaTransformer implements SchemaTransformer
2321
{
2422
private final int sinceVersion;
2523

26-
public SinceVersionSchemaTransformer(final int sinceVersion)
24+
SinceVersionSchemaTransformer(final int sinceVersion)
2725
{
2826
this.sinceVersion = sinceVersion;
2927
}
3028

29+
/**
30+
* {@inheritDoc}
31+
*/
3132
public MessageSchema transform(final MessageSchema originalSchema)
3233
{
3334
final Collection<Type> types = originalSchema.types();
3435
final Map<String, Type> newTypes = new HashMap<>();
3536

36-
for (Type type : types)
37+
for (final Type type : types)
3738
{
3839
if (type.sinceVersion() <= this.sinceVersion)
3940
{
@@ -43,11 +44,14 @@ public MessageSchema transform(final MessageSchema originalSchema)
4344

4445
final Collection<Message> messages = originalSchema.messages();
4546
final Map<Long, Message> newMessages = new HashMap<>();
46-
for (Message message : messages)
47+
for (final Message message : messages)
4748
{
48-
if (message.sinceVersion() <= this.sinceVersion)
49+
final List<Field> newFields = removeFields(message.fields(), sinceVersion);
50+
final Message newMessage = new Message(message, newFields);
51+
52+
if (newMessage.sinceVersion() <= this.sinceVersion)
4953
{
50-
newMessages.put((long)message.id(), message);
54+
newMessages.put((long)newMessage.id(), newMessage);
5155
}
5256
}
5357

@@ -63,6 +67,30 @@ public MessageSchema transform(final MessageSchema originalSchema)
6367
newMessages);
6468
}
6569

70+
private List<Field> removeFields(final List<Field> fields, final int sinceVersion)
71+
{
72+
final ArrayList<Field> newFields = new ArrayList<>();
73+
for (final Field field : fields)
74+
{
75+
if (field.sinceVersion() > sinceVersion)
76+
{
77+
continue;
78+
}
79+
80+
Field newField = field;
81+
List<Field> groupFields = field.groupFields();
82+
if (null != groupFields && !groupFields.isEmpty())
83+
{
84+
groupFields = removeFields(groupFields, sinceVersion);
85+
newField = new Field(field, groupFields);
86+
}
87+
88+
newFields.add(newField);
89+
}
90+
91+
return newFields;
92+
}
93+
6694
int sinceVersion()
6795
{
6896
return sinceVersion;

sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SchemaTransformerFactoryTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ void shouldAllSchemasAsOnlyInput()
4242
final SchemaTransformer delegate = schemaTransformerFactory.delegate();
4343
assertInstanceOf(SinceVersionSchemaTransformer.class, delegate);
4444

45-
SinceVersionSchemaTransformer transformer = (SinceVersionSchemaTransformer)delegate;
45+
final SinceVersionSchemaTransformer transformer = (SinceVersionSchemaTransformer)delegate;
4646
assertEquals(5, transformer.sinceVersion());
4747
}
4848

@@ -53,7 +53,7 @@ void shouldHandleMultiSchemaTransformation()
5353
final SchemaTransformer delegate = schemaTransformerFactory.delegate();
5454
assertInstanceOf(IdKeyedSchemaTransformer.class, delegate);
5555

56-
IdKeyedSchemaTransformer transformer = (IdKeyedSchemaTransformer)delegate;
56+
final IdKeyedSchemaTransformer transformer = (IdKeyedSchemaTransformer)delegate;
5757
final SinceVersionSchemaTransformer schemaTransformer1 =
5858
(SinceVersionSchemaTransformer)transformer.lookupTransformer(1);
5959
assertEquals(20, schemaTransformer1.sinceVersion());

sbe-tool/src/test/java/uk/co/real_logic/sbe/xml/SinceVersionSchemaTransformerTest.java

Lines changed: 61 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@
1919
import org.junit.jupiter.params.provider.ValueSource;
2020
import uk.co.real_logic.sbe.Tests;
2121

22-
import java.util.ArrayList;
23-
import java.util.Collection;
24-
import java.util.Iterator;
22+
import java.util.*;
2523

24+
import static java.util.Comparator.comparing;
2625
import static org.junit.jupiter.api.Assertions.*;
2726
import static uk.co.real_logic.sbe.xml.XmlSchemaParser.parse;
2827

@@ -51,26 +50,65 @@ private static void assertMessageSinceVersionLessOrEqualTo(
5150
{
5251
final ArrayList<Message> transformedMessagesCopy = new ArrayList<>(transformedSchema.messages());
5352

54-
final Collection<Message> types = originalSchema.messages();
55-
for (Message message : types)
53+
final Collection<Message> messages = originalSchema.messages();
54+
for (final Message originalMessage : messages)
5655
{
57-
if (message.sinceVersion() <= filteringVersion)
56+
57+
if (originalMessage.sinceVersion() <= filteringVersion)
5858
{
59-
assertNotNull(
60-
findAndRemove(transformedMessagesCopy, message),
61-
"Message (" + message.name() + ") should be retained");
59+
final Message transformedMessage = findAndRemove(
60+
transformedMessagesCopy, originalMessage, comparing(Message::id));
61+
assertNotNull(transformedMessage, "Message (" + originalMessage.name() + ") should be retained");
62+
63+
assertFieldsSinceVersionLessOrEqualTo(
64+
filteringVersion, originalMessage.fields(), transformedMessage.fields());
6265
}
6366
else
6467
{
6568
assertNull(
66-
findAndRemove(transformedMessagesCopy, message),
67-
"Message (" + message.name() + ") should be removed");
69+
findAndRemove(transformedMessagesCopy, originalMessage, comparing(Message::id)),
70+
"Message (" + originalMessage.name() + ") should be removed");
6871
}
6972
}
7073

7174
assertTrue(transformedMessagesCopy.isEmpty(), "Messages should have been removed: " + transformedMessagesCopy);
7275
}
7376

77+
private static void assertFieldsSinceVersionLessOrEqualTo(
78+
final int filteringVersion,
79+
final List<Field> originalFields,
80+
final List<Field> transformedFields)
81+
{
82+
assertFalse(null == originalFields ^ null == transformedFields);
83+
if (null == originalFields)
84+
{
85+
return;
86+
}
87+
88+
final ArrayList<Field> transformedFieldsCopy = new ArrayList<>(transformedFields);
89+
90+
for (final Field originalField : originalFields)
91+
{
92+
if (originalField.sinceVersion() <= filteringVersion)
93+
{
94+
final Field transformedField = findAndRemove(
95+
transformedFieldsCopy, originalField, comparing(Field::name));
96+
assertNotNull(transformedField, "Field (" + originalField.name() + ") should be retained");
97+
98+
assertFieldsSinceVersionLessOrEqualTo(
99+
filteringVersion, originalField.groupFields(), transformedField.groupFields());
100+
}
101+
else
102+
{
103+
assertNull(
104+
findAndRemove(transformedFieldsCopy, originalField, comparing(Field::name)),
105+
"Field (" + originalField.name() + ") should be removed");
106+
}
107+
}
108+
109+
assertTrue(transformedFieldsCopy.isEmpty(), "Fields should have been removed: " + transformedFields);
110+
}
111+
74112
private static void assertTypeSinceVersionLessOrEqualTo(
75113
final int filteringVersion,
76114
final MessageSchema originalSchema,
@@ -79,50 +117,37 @@ private static void assertTypeSinceVersionLessOrEqualTo(
79117
final ArrayList<Type> transformedTypesCopy = new ArrayList<>(transformedSchema.types());
80118

81119
final Collection<Type> types = originalSchema.types();
82-
for (Type type : types)
120+
for (final Type type : types)
83121
{
84122
if (type.sinceVersion() <= filteringVersion)
85123
{
86124
assertNotNull(
87-
findAndRemove(transformedTypesCopy, type),
125+
findAndRemove(transformedTypesCopy, type, comparing(Type::name)),
88126
"Type (" + type.name() + ") should be retained");
89127
}
90128
else
91129
{
92130
assertNull(
93-
findAndRemove(transformedTypesCopy, type),
131+
findAndRemove(transformedTypesCopy, type, comparing(Type::name)),
94132
"Type (" + type.name() + ") should be removed");
95133
}
96134
}
97135

98136
assertTrue(transformedTypesCopy.isEmpty(), "Types should have been removed: " + transformedTypesCopy);
99137
}
100138

101-
private static Type findAndRemove(final ArrayList<Type> transformedTypesCopy, final Type type)
102-
{
103-
Type result = null;
104-
for (final Iterator<Type> it = transformedTypesCopy.iterator(); it.hasNext();)
105-
{
106-
final Type transformedType = it.next();
107-
if (type.name().equals(transformedType.name()))
108-
{
109-
result = transformedType;
110-
it.remove();
111-
}
112-
}
113-
114-
return result;
115-
}
116-
117-
private static Message findAndRemove(final ArrayList<Message> transformedMessagesCopy, final Message message)
139+
private static <T> T findAndRemove(
140+
final ArrayList<T> transformedTsCopy,
141+
final T original,
142+
final Comparator<T> comparator)
118143
{
119-
Message result = null;
120-
for (final Iterator<Message> it = transformedMessagesCopy.iterator(); it.hasNext();)
144+
T result = null;
145+
for (final Iterator<T> it = transformedTsCopy.iterator(); it.hasNext();)
121146
{
122-
final Message transformedMessage = it.next();
123-
if (message.id() == transformedMessage.id())
147+
final T transformedT = it.next();
148+
if (0 == comparator.compare(original, transformedT))
124149
{
125-
result = transformedMessage;
150+
result = transformedT;
126151
it.remove();
127152
}
128153
}

0 commit comments

Comments
 (0)