diff --git a/examples/quickstart/Lightstreamer-example-StockList-client-javascript b/examples/quickstart/Lightstreamer-example-StockList-client-javascript deleted file mode 160000 index ec8c3eb8..00000000 --- a/examples/quickstart/Lightstreamer-example-StockList-client-javascript +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ec8c3eb8c3edf60f6cc844594d87e24fe47c96d8 diff --git a/gradle.properties b/gradle.properties index 7c202f40..23a172c5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,3 @@ version = 0.1.0 deployDirName = deploy +quickstartDeployDirName = examples/quickstart/deploy diff --git a/kafka-connector-samples/src/main/java/com/lightstreamer/kafka_connector/samples/producer/FeedSimluator.java b/kafka-connector-samples/src/main/java/com/lightstreamer/kafka_connector/samples/producer/FeedSimluator.java index 8de64ea8..ca034ca2 100644 --- a/kafka-connector-samples/src/main/java/com/lightstreamer/kafka_connector/samples/producer/FeedSimluator.java +++ b/kafka-connector-samples/src/main/java/com/lightstreamer/kafka_connector/samples/producer/FeedSimluator.java @@ -19,10 +19,12 @@ import com.fasterxml.jackson.annotation.JsonProperty; -import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; -import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Random; import java.util.Timer; import java.util.TimerTask; @@ -35,7 +37,7 @@ public class FeedSimluator { public interface ExternalFeedListener { - void onEvent(Stock stock, boolean b); + void onEvent(Stock stock); } private static final Timer dispatcher = new Timer(); @@ -108,7 +110,7 @@ public interface ExternalFeedListener { }; /** Used to keep the contexts of the 30 stocks. */ - private final ArrayList stockGenerators = new ArrayList<>(); + private final List stockGenerators = new ArrayList<>(); private ExternalFeedListener listener; @@ -117,11 +119,11 @@ public interface ExternalFeedListener { * external broadcast feed. */ public void start() { - for (int i = 0; i < 30; i++) { + for (int i = 0; i < 10; i++) { StockProducer stock = new StockProducer(i); stockGenerators.add(stock); - long waitTime = stock.computeNextWaitTime(); - scheduleGenerator(stock, waitTime); + // long waitTime = stock.computeNextWaitTime(); + scheduleGenerator(stock, 0); } } @@ -135,7 +137,7 @@ public void setFeedListener(ExternalFeedListener listener) { /** * Generates new values and sends a new update event at the time the producer declared to do it. */ - private void scheduleGenerator(final StockProducer stock, long waitTime) { + private void scheduleGenerator(StockProducer stock, long waitTime) { dispatcher.schedule( new TimerTask() { public void run() { @@ -143,7 +145,7 @@ public void run() { synchronized (stock) { stock.computeNewValues(); if (listener != null) { - listener.onEvent(stock.getCurrentValues(false), false); + listener.onEvent(stock.getCurrentValues(true)); } nextWaitTime = stock.computeNextWaitTime(); } @@ -234,61 +236,56 @@ public void computeNewValues() { * is not strict). */ public Stock getCurrentValues(boolean fullData) { - Stock stock = new Stock(); - stock.name = name; - final HashMap event = new HashMap(); + HashMap event = new HashMap(); - String format = "HH:mm:ss"; - SimpleDateFormat formatter = new SimpleDateFormat(format); - Date now = new Date(); - event.put("time", formatter.format(now)); - event.put("timestamp", Long.toString(now.getTime())); - stock.time = formatter.format(now); - stock.timestamp = Long.toString(now.getTime()); + LocalDateTime now = LocalDateTime.now(); + event.put("time", now.format(DateTimeFormatter.ofPattern("HH:mm:ss"))); + event.put("timestamp", String.valueOf(now.toInstant(ZoneOffset.UTC).toEpochMilli())); addDecField("last_price", last, event); - stock.last_price = addDecField(last); if (other > last) { addDecField("ask", other, event); - stock.ask = addDecField(other); addDecField("bid", last, event); - stock.bid = addDecField(last); } else { addDecField("ask", last, event); - stock.ask = addDecField(last); addDecField("bid", other, event); - stock.bid = addDecField(other); } int quantity; quantity = uniform(1, 200) * 500; event.put("bid_quantity", Integer.toString(quantity)); - stock.bid_quantity = Integer.toString(quantity); quantity = uniform(1, 200) * 500; event.put("ask_quantity", Integer.toString(quantity)); - stock.ask_quantity = Integer.toString(quantity); double var = (last - ref) / (double) ref * 100; addDecField("pct_change", (int) (var * 100), event); - stock.pct_change = addDecField((int) (var * 100)); if ((last == min) || fullData) { addDecField("min", min, event); - stock.min = addDecField(min); } if ((last == max) || fullData) { addDecField("max", max, event); - stock.max = addDecField(max); } if (fullData) { event.put("stock_name", name); addDecField("ref_price", ref, event); - stock.ref_price = addDecField(ref); addDecField("open_price", open, event); - stock.open_price = addDecField(open); // since it's a simulator the item is always active event.put("item_status", "active"); - stock.item_status = "active"; } - return stock; + return new Stock( + name, + event.get("time"), + event.get("timestamp"), + event.get("last_price"), + event.get("ask"), + event.get("bid"), + event.get("bid_quantity"), + event.get("ask_quantity"), + event.get("pct_change"), + event.get("min"), + event.get("max"), + event.get("ref_price"), + event.get("open_price"), + event.get("item_status")); } private void addDecField(String fld, int val100, HashMap target) { @@ -297,10 +294,6 @@ private void addDecField(String fld, int val100, HashMap target) target.put(fld, buf); } - private String addDecField(int val100) { - return Double.toString((((double) val100) / 100)); - } - private long gaussian(double mean, double stddev) { double base = random.nextGaussian(); return (long) (base * stddev + mean); @@ -312,20 +305,19 @@ private int uniform(int min, int max) { } } - public static class Stock { - @JsonProperty public String name; - @JsonProperty public String time; - @JsonProperty public String timestamp; - @JsonProperty public String last_price; - @JsonProperty public String ask; - @JsonProperty public String bid; - @JsonProperty public String bid_quantity; - @JsonProperty public String ask_quantity; - @JsonProperty public String pct_change; - @JsonProperty public String min; - @JsonProperty public String max; - @JsonProperty public String ref_price; - @JsonProperty public String open_price; - @JsonProperty public String item_status; - } + public static record Stock( + @JsonProperty String name, + @JsonProperty String time, + @JsonProperty String timestamp, + @JsonProperty String last_price, + @JsonProperty String ask, + @JsonProperty String bid, + @JsonProperty String bid_quantity, + @JsonProperty String ask_quantity, + @JsonProperty String pct_change, + @JsonProperty String min, + @JsonProperty String max, + @JsonProperty String ref_price, + @JsonProperty String open_price, + @JsonProperty String item_status) {} } diff --git a/kafka-connector-samples/src/main/java/com/lightstreamer/kafka_connector/samples/producer/Producer.java b/kafka-connector-samples/src/main/java/com/lightstreamer/kafka_connector/samples/producer/Producer.java index 07775e53..4ab10d48 100644 --- a/kafka-connector-samples/src/main/java/com/lightstreamer/kafka_connector/samples/producer/Producer.java +++ b/kafka-connector-samples/src/main/java/com/lightstreamer/kafka_connector/samples/producer/Producer.java @@ -66,9 +66,9 @@ public void run() { } @Override - public void onEvent(Stock stock, boolean b) { + public void onEvent(Stock stock) { ProducerRecord record = - new ProducerRecord<>(this.topic, stock.name.replace(' ', '-'), stock); + new ProducerRecord<>(this.topic, stock.name().replace(' ', '-'), stock); producer.send( record, new Callback() { diff --git a/kafka-connector/src/connector/dist/adapters.xml b/kafka-connector/src/connector/dist/adapters.xml index 53fab04f..8c467219 100644 --- a/kafka-connector/src/connector/dist/adapters.xml +++ b/kafka-connector/src/connector/dist/adapters.xml @@ -141,13 +141,13 @@ #{VALUE.name} - #{TIMESTAMP} + #{VALUE.time} - #{PARTITION} + #{VALUE.timestamp} - #{OFFSET} + #{VALUE.last_price} #{VALUE.ask} diff --git a/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/ItemExpressionEvaluator.java b/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/ItemExpressionEvaluator.java index 8627a948..411564d5 100644 --- a/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/ItemExpressionEvaluator.java +++ b/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/ItemExpressionEvaluator.java @@ -46,7 +46,7 @@ enum ItemEvaluator implements ItemExpressionEvaluator { Pattern.compile("(([a-zA-Z\\._]\\w*)=([a-zA-Z0-9\\.\\[\\]\\*]+)),?")), SUBSCRIBED( - Pattern.compile("([a-zA-Z0-9_-]+)(-<(.*)>)?"), + Pattern.compile("([a-zA-Z0-9_-]+)(-\\[(.*)\\])?"), Pattern.compile("(([a-zA-Z\\._]\\w*)=([^,]+)),?")); private final Pattern gobal; diff --git a/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapper.java b/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapper.java index 28fd9122..0116d133 100644 --- a/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapper.java +++ b/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapper.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -120,11 +121,12 @@ public int mappedValuesSize() { @Override public Map filter(Selectors selectors) { - return valuesContainers.stream() + Map eventsMap = new HashMap<>(); + valuesContainers.stream() .filter(container -> container.selectors().equals(selectors)) .flatMap(container -> container.values().stream()) - .filter(v -> v.text() != null) - .collect(Collectors.toMap(Value::name, Value::text)); + .forEach(value -> eventsMap.put(value.name(), value.text())); + return eventsMap; } @Override diff --git a/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/avro/GenericRecordSelectorsSuppliers.java b/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/avro/GenericRecordSelectorsSuppliers.java index 5554fb42..0dff4d0e 100644 --- a/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/avro/GenericRecordSelectorsSuppliers.java +++ b/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/avro/GenericRecordSelectorsSuppliers.java @@ -169,7 +169,7 @@ protected Value eval(GenericRecord record) { LinkedNode> currentNode = linkedNode; while (currentNode != null) { if (value == null) { - ValueException.throwNullObject(currentNode.previous().value().name()); + ValueException.throwFieldNotFound(currentNode.value().name()); continue; } if (value instanceof GenericRecord genericRecord) { @@ -185,7 +185,7 @@ protected Value eval(GenericRecord record) { ValueException.throwNonComplexObjectRequired(expression()); } - String text = value != null ? value.toString() : "NULL"; + String text = value != null ? value.toString() : null; return Value.of(name(), text); } } diff --git a/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/json/JsonNodeSelectorsSuppliers.java b/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/json/JsonNodeSelectorsSuppliers.java index 04060a20..564ebb2d 100644 --- a/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/json/JsonNodeSelectorsSuppliers.java +++ b/kafka-connector/src/main/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/json/JsonNodeSelectorsSuppliers.java @@ -148,7 +148,7 @@ Value eval(JsonNode node) { ValueException.throwNonComplexObjectRequired(expression()); } - String text = !node.isNull() ? node.asText() : "NULL"; + String text = !node.isNull() ? node.asText() : null; return Value.of(name(), text); } } diff --git a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/ItemTemplatesTest.java b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/ItemTemplatesTest.java index 73c6b731..fc48c4d7 100644 --- a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/ItemTemplatesTest.java +++ b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/ItemTemplatesTest.java @@ -120,11 +120,11 @@ public void shouldOneToMany() { ItemTemplates templates = Items.templatesFrom(topicsConfig, selected); assertThat(templates.topics()).containsExactly("topic"); - Item subcribingItem1 = Items.itemFrom("template-family-", ""); + Item subcribingItem1 = Items.itemFrom("template-family-[topic=aSpecificTopic]", ""); assertThat(templates.matches(subcribingItem1)).isTrue(); Item subcribingItem2 = - Items.itemFrom("template-relatives-", ""); + Items.itemFrom("template-relatives-[topic=anotherSpecificTopic]", ""); assertThat(templates.matches(subcribingItem2)).isTrue(); RecordMapper mapper = @@ -163,7 +163,7 @@ public void shouldManyToOne() { ItemTemplates templates = Items.templatesFrom(topicsConfig, suppliers); assertThat(templates.topics()).containsExactly("new_orders", "past_orders"); - Item subcribingItem = Items.itemFrom("template-orders-", ""); + Item subcribingItem = Items.itemFrom("template-orders-[topic=aSpecifgicTopic]", ""); assertThat(templates.matches(subcribingItem)).isTrue(); RecordMapper mapper = @@ -255,13 +255,13 @@ static Stream templateArgs() { List.of("item-#{key=KEY,value=VALUE}"), List.of( Items.itemFrom("item", new Object()), - Items.itemFrom("item-", new Object()), - Items.itemFrom("item-", new Object()), - Items.itemFrom("item-", new Object())), + Items.itemFrom("item-[key=key]", new Object()), + Items.itemFrom("item-[key=key,value=value]", new Object()), + Items.itemFrom("item-[value=value]", new Object())), List.of( Items.itemFrom("nonRoutable", new Object()), - Items.itemFrom("item-", new Object()), - Items.itemFrom("item-", new Object()))), + Items.itemFrom("item-[key=anotherKey]", new Object()), + Items.itemFrom("item-[value=anotherValue]", new Object()))), arguments( List.of( "item-#{key=KEY,value=VALUE}", @@ -269,17 +269,17 @@ static Stream templateArgs() { "myItem-#{topic=TOPIC}"), List.of( Items.itemFrom("item", new Object()), - Items.itemFrom("item-", new Object()), - Items.itemFrom("item-", new Object()), - Items.itemFrom("item-", new Object()), - Items.itemFrom("item-", new Object()), - Items.itemFrom("myItem-", new Object())), + Items.itemFrom("item-[key=key]", new Object()), + Items.itemFrom("item-[key=key,value=value]", new Object()), + Items.itemFrom("item-[value=value]", new Object()), + Items.itemFrom("item-[topic=topic]", new Object()), + Items.itemFrom("myItem-[topic=topic]", new Object())), List.of( Items.itemFrom("nonRoutable", new Object()), - Items.itemFrom("item-", new Object()), - Items.itemFrom("item-", new Object()), - Items.itemFrom("item-", new Object()), - Items.itemFrom("myItem-", new Object())))); + Items.itemFrom("item-[key=anotherKey]", new Object()), + Items.itemFrom("item-[value=anotherValue]", new Object()), + Items.itemFrom("item-[topic=anotherTopic]", new Object()), + Items.itemFrom("myItem-[topic=anotherTopic]", new Object())))); } @ParameterizedTest diff --git a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/ItemTest.java b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/ItemTest.java index 3df58a22..c79241f5 100644 --- a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/ItemTest.java +++ b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/ItemTest.java @@ -105,7 +105,7 @@ public void shouldNotMatcDueToDifferentPrefix() { item-first | item-first item_123_ | item_123_ item- | item- - prefix-<> | prefix + prefix-[] | prefix """) public void shouldMakeWithEmptySchemaKeys(String input, String expectedPrefix) { Object handle = new Object(); @@ -124,14 +124,14 @@ public void shouldMakeWithEmptySchemaKeys(String input, String expectedPrefix) { textBlock = """ INPUT | EXPECTED_PREFIX | EXPECTED_NAME | EXPECTED_VALUE - item- | item | name | field1 - item-first- | item-first | height | 12.34 - item_123_- | item_123_ | test | \\ - item- | item | test | "" - prefix-> | prefix | test | > - item- | item | test | value + item-[name=field1] | item | name | field1 + item-first-[height=12.34] | item-first | height | 12.34 + item_123_-[test=\\] | item_123_ | test | \\ + item-[test=""] | item | test | "" + prefix-[test=]] | prefix | test | ] + item-[test=value,] | item | test | value item- | item- | | - item-<> | item | | + item-[] | item | | """) public void shouldMakeWithValue( String input, String expectedPrefix, String expectedName, String expectedValue) { @@ -155,7 +155,7 @@ public void shouldMakeWithValue( textBlock = """ INPUT | EXPECTED_NAME1 | EXPECTED_VALUE1 | EXPECTED_NAME2 | EXPECTED_VALUE2 - item- | name1 | field1 | name2 | field2 + item-[name1=field1,name2=field2] | name1 | field1 | name2 | field2 """) public void shouldMakeWithMoreValues( String input, String name1, String val1, String name2, String value2) { diff --git a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapperAvroTest.java b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapperAvroTest.java index 2e7063c0..95532270 100644 --- a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapperAvroTest.java +++ b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapperAvroTest.java @@ -83,7 +83,7 @@ public void shouldBuildMapperWithDifferentSelectors() { } @Test - public void shoulMapEmpty() { + public void shouldMapEmpty() { RecordMapper mapper = builder().build(); ConsumerRecord kafkaRecord = @@ -95,7 +95,7 @@ public void shoulMapEmpty() { } @Test - public void shoulMapWithValues() { + public void shouldMapWithValues() { RecordMapper mapper = builder() .withSelectors(selectors("test1", Map.of("aKey", "PARTITION"))) @@ -163,4 +163,26 @@ public void shouldFilter() { assertThat(otherPeopleNames) .containsExactly("secondChildName", "anna", "grandChildName", "terence"); } + + @Test + public void shouldFilterWithNullValues() { + Selectors selectors = + selectors( + "test", + Map.of( + "name", + "VALUE.children[0].name", + "signature", + "VALUE.children[0].signature")); + + RecordMapper mapper = builder().withSelectors(selectors).build(); + + ConsumerRecord kafkaRecord = + ConsumerRecords.record("", GenericRecordProvider.RECORD); + MappedRecord mappedRecord = mapper.map(kafkaRecord); + assertThat(mappedRecord.mappedValuesSize()).isEqualTo(2); + + Map parentName = mappedRecord.filter(selectors); + assertThat(parentName).containsExactly("name", "alex", "signature", null); + } } diff --git a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapperJsonTest.java b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapperJsonTest.java index 571dc10b..7f68077a 100644 --- a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapperJsonTest.java +++ b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapperJsonTest.java @@ -79,7 +79,7 @@ public void shouldBuildMapperWithDifferentSelectors() { } @Test - public void shoulMapEmpty() { + public void shouldMapEmpty() { RecordMapper mapper = builder().build(); ConsumerRecord kafkaRecord = @@ -91,7 +91,7 @@ public void shoulMapEmpty() { } @Test - public void shoulMapWithValues() { + public void shouldMapWithValues() { RecordMapper mapper = builder() .withSelectors(selectors("test1", Map.of("aKey", "PARTITION"))) @@ -158,4 +158,26 @@ public void shouldFilter() { assertThat(otherPeopleNames) .containsExactly("secondChildName", "anna", "grandChildName", "terence"); } + + @Test + public void shouldFilterWithNullValues() { + Selectors selectors = + selectors( + "test", + Map.of( + "name", + "VALUE.children[0].name", + "signature", + "VALUE.children[0].signature")); + + RecordMapper mapper = builder().withSelectors(selectors).build(); + + ConsumerRecord kafkaRecord = + ConsumerRecords.record("", JsonNodeProvider.RECORD); + MappedRecord mappedRecord = mapper.map(kafkaRecord); + assertThat(mappedRecord.mappedValuesSize()).isEqualTo(2); + + Map parentName = mappedRecord.filter(selectors); + assertThat(parentName).containsExactly("name", "alex", "signature", null); + } } diff --git a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapperStringTest.java b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapperStringTest.java index ff47cc4c..a52e2725 100644 --- a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapperStringTest.java +++ b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/RecordMapperStringTest.java @@ -73,7 +73,7 @@ public void shouldBuildMapperWithDifferentSelectors() { } @Test - public void shoulMapEmpty() { + public void shouldMapEmpty() { RecordMapper mapper = builder().build(); ConsumerRecord kafkaRecord = ConsumerRecords.record("", "aValue"); @@ -84,7 +84,7 @@ public void shoulMapEmpty() { } @Test - public void shoulMapWithValues() { + public void shouldMapWithValues() { RecordMapper mapper = builder() .withSelectors(selectors("test1", Map.of("aKey", "PARTITION"))) @@ -115,23 +115,10 @@ public void shouldFilter() { Selectors valueSelectors = selectors("test", Map.of("name", "VALUE")); Selectors keySelectors = selectors("test", Map.of("name", "KEY")); - // Selectors childSelectors2 = - // selectors( - // "test", - // Map.of( - // "secondChildName", - // "VALUE.children[1].name", - // "grandChildName", - // "VALUE.children[1].children[1].name")); - RecordMapper mapper = - builder() - .withSelectors(valueSelectors) - .withSelectors(keySelectors) - // .withSelectors(childSelectors2) - .build(); + builder().withSelectors(valueSelectors).withSelectors(keySelectors).build(); - ConsumerRecord kafkaRecord = ConsumerRecords.record("", null); + ConsumerRecord kafkaRecord = ConsumerRecords.record("", "aValue"); MappedRecord mappedRecord = mapper.map(kafkaRecord); assertThat(mappedRecord.mappedValuesSize()).isEqualTo(2); @@ -140,9 +127,24 @@ public void shouldFilter() { Map firstChildName = mappedRecord.filter(keySelectors); assertThat(firstChildName).containsExactly("name", ""); + } + + @Test + public void shouldFilterNulls() { + Selectors valueSelectors = selectors("test", Map.of("name", "VALUE")); + Selectors keySelectors = selectors("test", Map.of("name", "KEY")); - // Map otherPeopleNames = mappedRecord.filter(childSelectors2); - // assertThat(otherPeopleNames) - // .containsExactly("secondChildName", "anna", "grandChildName", "terence"); + RecordMapper mapper = + builder().withSelectors(valueSelectors).withSelectors(keySelectors).build(); + + ConsumerRecord kafkaRecord = ConsumerRecords.record("", null); + MappedRecord mappedRecord = mapper.map(kafkaRecord); + assertThat(mappedRecord.mappedValuesSize()).isEqualTo(2); + + Map parentName = mappedRecord.filter(valueSelectors); + assertThat(parentName).containsExactly("name", null); + + Map firstChildName = mappedRecord.filter(keySelectors); + assertThat(firstChildName).containsExactly("name", ""); } } diff --git a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/avro/GenericRecordSelectorTest.java b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/avro/GenericRecordSelectorTest.java index 893ca6da..f22a666b 100644 --- a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/avro/GenericRecordSelectorTest.java +++ b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/avro/GenericRecordSelectorTest.java @@ -24,6 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; +import com.google.common.truth.StringSubject; import com.lightstreamer.kafka_connector.adapters.config.ConnectorConfig; import com.lightstreamer.kafka_connector.adapters.mapping.ExpressionException; import com.lightstreamer.kafka_connector.adapters.mapping.selectors.KeySelector; @@ -82,27 +83,32 @@ public void shouldGetDeserializer() { delimiter = '|', textBlock = """ - EXPRESSION | EXPECTED - VALUE.name | joe - VALUE.preferences['pref1'] | pref_value1 - VALUE.preferences['pref2'] | pref_value2 - VALUE.documents['id'].doc_id | ID123 - VALUE.documents['id'].doc_type | ID - VALUE.type | TYPE1 - VALUE.signature | [97, 98, 99, 100] - VALUE.children[0].name | alex - VALUE.children[0]['name'] | alex - VALUE.children[0].signature | NULL - VALUE.children[1].name | anna - VALUE.children[2].name | serena - VALUE.children[3] | NULL - VALUE.children[1].children[0].name | gloria - VALUE.children[1].children[1].name | terence - VALUE.children[1].children[1]['name'] | terence - """) + EXPRESSION | EXPECTED + VALUE.name | joe + VALUE.preferences['pref1'] | pref_value1 + VALUE.preferences['pref2'] | pref_value2 + VALUE.documents['id'].doc_id | ID123 + VALUE.documents['id'].doc_type | ID + VALUE.type | TYPE1 + VALUE.signature | [97, 98, 99, 100] + VALUE.children[0].name | alex + VALUE.children[0]['name'] | alex + VALUE.children[0].signature | NULL + VALUE.children[1].name | anna + VALUE.children[2].name | serena + VALUE.children[3] | NULL + VALUE.children[1].children[0].name | gloria + VALUE.children[1].children[1].name | terence + VALUE.children[1].children[1]['name'] | terence + """) public void shouldExtractValue(String expression, String expectedValue) { ValueSelector selector = valueSelector(expression); - assertThat(selector.extract(fromValue(RECORD)).text()).isEqualTo(expectedValue); + StringSubject subject = assertThat(selector.extract(fromValue(RECORD)).text()); + if (expectedValue.equals("NULL")) { + subject.isNull(); + } else { + subject.isEqualTo(expectedValue); + } } @ParameterizedTest(name = "[{index}] {arguments}") @@ -110,20 +116,20 @@ public void shouldExtractValue(String expression, String expectedValue) { useHeadersInDisplayName = true, textBlock = """ - EXPRESSION, EXPECTED_ERROR_MESSAGE - VALUE.no_attrib, Field [no_attrib] not found - VALUE.children[0].no_attrib, Field [no_attrib] not found - VALUE.no_children[0], Field [no_children] not found - VALUE.name[0], Current field is not indexed - VALUE.preferences, The expression [VALUE.preferences] must evaluate to a non-complex object - VALUE.children, The expression [VALUE.children] must evaluate to a non-complex object - VALUE.children[0]['no_key'], Field [no_key] not found - VALUE.children[0], The expression [VALUE.children[0]] must evaluate to a non-complex object - VALUE.children[3].name, Current fieldField not found at index [3] - VALUE.children[4], Field not found at index [4] - VALUE.children[4].name, Field not found at index [4] - VALUE.type.attrib, Current field [EnumSymbol] is a terminal object - """) + EXPRESSION, EXPECTED_ERROR_MESSAGE + VALUE.no_attrib, Field [no_attrib] not found + VALUE.children[0].no_attrib, Field [no_attrib] not found + VALUE.no_children[0], Field [no_children] not found + VALUE.name[0], Current field is not indexed + VALUE.preferences, The expression [VALUE.preferences] must evaluate to a non-complex object + VALUE.children, The expression [VALUE.children] must evaluate to a non-complex object + VALUE.children[0]['no_key'], Field [no_key] not found + VALUE.children[0], The expression [VALUE.children[0]] must evaluate to a non-complex object + VALUE.children[3].name, Field [name] not found + VALUE.children[4], Field not found at index [4] + VALUE.children[4].name, Field not found at index [4] + VALUE.type.attrib, Current field [EnumSymbol] is a terminal object + """) public void shouldNotExtractValue(String expression, String errorMessage) { ValueSelector selector = valueSelector(expression); ValueException ve = @@ -137,16 +143,16 @@ public void shouldNotExtractValue(String expression, String errorMessage) { useHeadersInDisplayName = true, textBlock = """ - EXPRESSION, EXPECTED - KEY.name, joe - KEY.children[0].name, alex - KEY.children[0]['name'], alex - KEY.children[1].name, anna - KEY.children[2].name, serena - KEY.children[1].children[0].name, gloria - KEY.children[1].children[1].name, terence - KEY.children[1].children[1]['name'], terence - """) + EXPRESSION, EXPECTED + KEY.name, joe + KEY.children[0].name, alex + KEY.children[0]['name'], alex + KEY.children[1].name, anna + KEY.children[2].name, serena + KEY.children[1].children[0].name, gloria + KEY.children[1].children[1].name, terence + KEY.children[1].children[1]['name'], terence + """) public void shouldExtractKey(String expression, String expectedValue) { KeySelector selector = keySelector(expression); assertThat(selector.extract(fromKey(RECORD)).text()).isEqualTo(expectedValue); @@ -157,17 +163,17 @@ public void shouldExtractKey(String expression, String expectedValue) { useHeadersInDisplayName = true, textBlock = """ - EXPRESSION, EXPECTED_ERROR_MESSAGE - KEY.no_attrib, Field [no_attrib] not found - KEY.children[0].no_attrib, Field [no_attrib] not found - KEY.no_children[0], Field [no_children] not found - KEY.name[0], Current field is not indexed - KEY.preferences, The expression [KEY.preferences] must evaluate to a non-complex object - KEY.children, The expression [KEY.children] must evaluate to a non-complex object - KEY.children[0]['no_key'], Field [no_key] not found - KEY.children[0], The expression [KEY.children[0]] must evaluate to a non-complex object - KEY.children[3].name, Field not found at index [3] - """) + EXPRESSION, EXPECTED_ERROR_MESSAGE + KEY.no_attrib, Field [no_attrib] not found + KEY.children[0].no_attrib, Field [no_attrib] not found + KEY.no_children[0], Field [no_children] not found + KEY.name[0], Current field is not indexed + KEY.preferences, The expression [KEY.preferences] must evaluate to a non-complex object + KEY.children, The expression [KEY.children] must evaluate to a non-complex object + KEY.children[0]['no_key'], Field [no_key] not found + KEY.children[0], The expression [KEY.children[0]] must evaluate to a non-complex object + KEY.children[3].name, Field [name] not found + """) public void shouldNotExtractKey(String expression, String errorMessage) { KeySelector selector = keySelector(expression); ValueException ve = @@ -180,19 +186,19 @@ public void shouldNotExtractKey(String expression, String errorMessage) { useHeadersInDisplayName = true, textBlock = """ - ESPRESSION, EXPECTED_ERROR_MESSAGE - '', Expected the root token [KEY] while evaluating [name] - invalidKey, Expected the root token [KEY] while evaluating [name] - KEY, Found the invalid expression [KEY] while evaluating [name] - KEY., Found the invalid expression [KEY.] while evaluating [name] - KEY.., Found the invalid expression [KEY..] with missing tokens while evaluating [name] - KEY.attrib[], Found the invalid indexed expression [KEY.attrib[]] while evaluating [name] - KEY.attrib[0]xsd, Found the invalid indexed expression [KEY.attrib[0]xsd] while evaluating [name] - KEY.attrib[], Found the invalid indexed expression [KEY.attrib[]] while evaluating [name] - KEY.attrib[a], Found the invalid indexed expression [KEY.attrib[a]] while evaluating [name] - KEY.attrib[a]., Found the invalid indexed expression [KEY.attrib[a].] while evaluating [name] - KEY.attrib[0]., Found the invalid indexed expression [KEY.attrib[0].] while evaluating [name] - """) + ESPRESSION, EXPECTED_ERROR_MESSAGE + '', Expected the root token [KEY] while evaluating [name] + invalidKey, Expected the root token [KEY] while evaluating [name] + KEY, Found the invalid expression [KEY] while evaluating [name] + KEY., Found the invalid expression [KEY.] while evaluating [name] + KEY.., Found the invalid expression [KEY..] with missing tokens while evaluating [name] + KEY.attrib[], Found the invalid indexed expression [KEY.attrib[]] while evaluating [name] + KEY.attrib[0]xsd, Found the invalid indexed expression [KEY.attrib[0]xsd] while evaluating [name] + KEY.attrib[], Found the invalid indexed expression [KEY.attrib[]] while evaluating [name] + KEY.attrib[a], Found the invalid indexed expression [KEY.attrib[a]] while evaluating [name] + KEY.attrib[a]., Found the invalid indexed expression [KEY.attrib[a].] while evaluating [name] + KEY.attrib[0]., Found the invalid indexed expression [KEY.attrib[0].] while evaluating [name] + """) public void shouldNotCreateKeySelector(String expression, String expectedErrorMessage) { ExpressionException ee = assertThrows(ExpressionException.class, () -> keySelector(expression)); @@ -204,18 +210,18 @@ public void shouldNotCreateKeySelector(String expression, String expectedErrorMe useHeadersInDisplayName = true, textBlock = """ - ESPRESSION, EXPECTED_ERROR_MESSAGE - '', Expected the root token [VALUE] while evaluating [name] - invalidValue, Expected the root token [VALUE] while evaluating [name] - VALUE, Found the invalid expression [VALUE] while evaluating [name] - VALUE., Found the invalid expression [VALUE.] while evaluating [name] - VALUE.., Found the invalid expression [VALUE..] with missing tokens while evaluating [name] - VALUE.attrib[], Found the invalid indexed expression [VALUE.attrib[]] while evaluating [name] - VALUE.attrib[0]xsd, Found the invalid indexed expression [VALUE.attrib[0]xsd] while evaluating [name] - VALUE.attrib[], Found the invalid indexed expression [VALUE.attrib[]] while evaluating [name] - VALUE.attrib[a], Found the invalid indexed expression [VALUE.attrib[a]] while evaluating [name] - VALUE.attrib[a]., Found the invalid indexed expression [VALUE.attrib[a].] while evaluating [name] - """) + ESPRESSION, EXPECTED_ERROR_MESSAGE + '', Expected the root token [VALUE] while evaluating [name] + invalidValue, Expected the root token [VALUE] while evaluating [name] + VALUE, Found the invalid expression [VALUE] while evaluating [name] + VALUE., Found the invalid expression [VALUE.] while evaluating [name] + VALUE.., Found the invalid expression [VALUE..] with missing tokens while evaluating [name] + VALUE.attrib[], Found the invalid indexed expression [VALUE.attrib[]] while evaluating [name] + VALUE.attrib[0]xsd, Found the invalid indexed expression [VALUE.attrib[0]xsd] while evaluating [name] + VALUE.attrib[], Found the invalid indexed expression [VALUE.attrib[]] while evaluating [name] + VALUE.attrib[a], Found the invalid indexed expression [VALUE.attrib[a]] while evaluating [name] + VALUE.attrib[a]., Found the invalid indexed expression [VALUE.attrib[a].] while evaluating [name] + """) public void shouldNotCreateValueSelector(String expression, String expectedErrorMessage) { ExpressionException ee = assertThrows(ExpressionException.class, () -> valueSelector(expression)); diff --git a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/json/JsonNodeSelectorTest.java b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/json/JsonNodeSelectorTest.java index f3c1a6f3..0a21a840 100644 --- a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/json/JsonNodeSelectorTest.java +++ b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/mapping/selectors/json/JsonNodeSelectorTest.java @@ -25,6 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import com.fasterxml.jackson.databind.JsonNode; +import com.google.common.truth.StringSubject; import com.lightstreamer.kafka_connector.adapters.config.ConnectorConfig; import com.lightstreamer.kafka_connector.adapters.mapping.ExpressionException; import com.lightstreamer.kafka_connector.adapters.mapping.selectors.KeySelector; @@ -70,22 +71,27 @@ public void shouldGetDeserializer() { delimiter = '|', textBlock = """ - EXPRESSION | EXPECTED_VALUE - VALUE.name | joe - VALUE.signature | YWJjZA== - VALUE.children[0].name | alex - VALUE.children[0]['name'] | alex - VALUE.children[0].signature | NULL - VALUE.children[1].name | anna - VALUE.children[2].name | serena - VALUE.children[3] | NULL - VALUE.children[1].children[0].name | gloria - VALUE.children[1].children[1].name | terence - VALUE.children[1].children[1]['name'] | terence - """) + EXPRESSION | EXPECTED_VALUE + VALUE.name | joe + VALUE.signature | YWJjZA== + VALUE.children[0].name | alex + VALUE.children[0]['name'] | alex + VALUE.children[0].signature | NULL + VALUE.children[1].name | anna + VALUE.children[2].name | serena + VALUE.children[3] | NULL + VALUE.children[1].children[0].name | gloria + VALUE.children[1].children[1].name | terence + VALUE.children[1].children[1]['name'] | terence + """) public void shouldExtractValue(String expression, String expectedValue) { ValueSelector selector = valueSelector(expression); - assertThat(selector.extract(fromValue(RECORD)).text()).isEqualTo(expectedValue); + StringSubject subject = assertThat(selector.extract(fromValue(RECORD)).text()); + if (expectedValue.equals("NULL")) { + subject.isNull(); + } else { + subject.isEqualTo(expectedValue); + } } @ParameterizedTest(name = "[{index}] {arguments}") @@ -93,18 +99,18 @@ public void shouldExtractValue(String expression, String expectedValue) { useHeadersInDisplayName = true, textBlock = """ - EXPRESSION, EXPECTED_ERROR_MESSAGE - VALUE.no_attrib, Field [no_attrib] not found - VALUE.children[0].no_attrib, Field [no_attrib] not found - VALUE.no_children[0], Field [no_children] not found - VALUE.name[0], Current field is not indexed - VALUE.children, The expression [VALUE.children] must evaluate to a non-complex object - VALUE.children[0]['no_key'], Field [no_key] not found - VALUE.children[0], The expression [VALUE.children[0]] must evaluate to a non-complex object - VALUE.children[3].name, Current fieldField not found at index [3] - VALUE.children[4], Field not found at index [4] - VALUE.children[4].name, Field not found at index [4] - """) + EXPRESSION, EXPECTED_ERROR_MESSAGE + VALUE.no_attrib, Field [no_attrib] not found + VALUE.children[0].no_attrib, Field [no_attrib] not found + VALUE.no_children[0], Field [no_children] not found + VALUE.name[0], Current field is not indexed + VALUE.children, The expression [VALUE.children] must evaluate to a non-complex object + VALUE.children[0]['no_key'], Field [no_key] not found + VALUE.children[0], The expression [VALUE.children[0]] must evaluate to a non-complex object + VALUE.children[3].name, Field [name] not found + VALUE.children[4], Field not found at index [4] + VALUE.children[4].name, Field not found at index [4] + """) public void shouldNotExtractValue(String expression, String errorMessage) { ValueSelector selector = valueSelector(expression); ValueException ve = @@ -118,16 +124,16 @@ public void shouldNotExtractValue(String expression, String errorMessage) { useHeadersInDisplayName = true, textBlock = """ - ESPRESSION, EXPECTED_VALUE - KEY.name, joe - KEY.children[0].name, alex - KEY.children[0]['name'], alex - KEY.children[1].name, anna - KEY.children[2].name, serena - KEY.children[1].children[0].name, gloria - KEY.children[1].children[1].name, terence - KEY.children[1].children[1]['name'], terence - """) + ESPRESSION, EXPECTED_VALUE + KEY.name, joe + KEY.children[0].name, alex + KEY.children[0]['name'], alex + KEY.children[1].name, anna + KEY.children[2].name, serena + KEY.children[1].children[0].name, gloria + KEY.children[1].children[1].name, terence + KEY.children[1].children[1]['name'], terence + """) public void shouldExtractKey(String expression, String expectedValue) { KeySelector selector = keySelector(expression); assertThat(selector.extract(fromKey(RECORD)).text()).isEqualTo(expectedValue); @@ -138,15 +144,15 @@ public void shouldExtractKey(String expression, String expectedValue) { useHeadersInDisplayName = true, textBlock = """ - EXPRESSION, EXPECTED_ERROR_MESSAGE - KEY.no_attrib, Field [no_attrib] not found - KEY.children[0].no_attrib, Field [no_attrib] not found - KEY.no_children[0], Field [no_children] not found - KEY.name[0], Current field is not indexed - KEY.children[0]['no_key'], Field [no_key] not found - KEY.children[0], The expression [KEY.children[0]] must evaluate to a non-complex object - KEY.children[3].name, Field not found at index [3] - """) + EXPRESSION, EXPECTED_ERROR_MESSAGE + KEY.no_attrib, Field [no_attrib] not found + KEY.children[0].no_attrib, Field [no_attrib] not found + KEY.no_children[0], Field [no_children] not found + KEY.name[0], Current field is not indexed + KEY.children[0]['no_key'], Field [no_key] not found + KEY.children[0], The expression [KEY.children[0]] must evaluate to a non-complex object + KEY.children[3].name, Field [name] not found + """) public void shouldNotExtractKey(String expression, String errorMessage) { KeySelector selector = keySelector(expression); ValueException ve = @@ -159,19 +165,19 @@ public void shouldNotExtractKey(String expression, String errorMessage) { useHeadersInDisplayName = true, textBlock = """ - ESPRESSION, EXPECTED_ERROR_MESSAGE - '', Expected the root token [KEY] while evaluating [name] - invalidKey, Expected the root token [KEY] while evaluating [name] - KEY, Found the invalid expression [KEY] while evaluating [name] - KEY., Found the invalid expression [KEY.] while evaluating [name] - KEY.., Found the invalid expression [KEY..] with missing tokens while evaluating [name] - KEY.attrib[], Found the invalid indexed expression [KEY.attrib[]] while evaluating [name] - KEY.attrib[0]xsd, Found the invalid indexed expression [KEY.attrib[0]xsd] while evaluating [name] - KEY.attrib[], Found the invalid indexed expression [KEY.attrib[]] while evaluating [name] - KEY.attrib[a], Found the invalid indexed expression [KEY.attrib[a]] while evaluating [name] - KEY.attrib[a]., Found the invalid indexed expression [KEY.attrib[a].] while evaluating [name] - KEY.attrib[0]., Found the invalid indexed expression [KEY.attrib[0].] while evaluating [name] - """) + ESPRESSION, EXPECTED_ERROR_MESSAGE + '', Expected the root token [KEY] while evaluating [name] + invalidKey, Expected the root token [KEY] while evaluating [name] + KEY, Found the invalid expression [KEY] while evaluating [name] + KEY., Found the invalid expression [KEY.] while evaluating [name] + KEY.., Found the invalid expression [KEY..] with missing tokens while evaluating [name] + KEY.attrib[], Found the invalid indexed expression [KEY.attrib[]] while evaluating [name] + KEY.attrib[0]xsd, Found the invalid indexed expression [KEY.attrib[0]xsd] while evaluating [name] + KEY.attrib[], Found the invalid indexed expression [KEY.attrib[]] while evaluating [name] + KEY.attrib[a], Found the invalid indexed expression [KEY.attrib[a]] while evaluating [name] + KEY.attrib[a]., Found the invalid indexed expression [KEY.attrib[a].] while evaluating [name] + KEY.attrib[0]., Found the invalid indexed expression [KEY.attrib[0].] while evaluating [name] + """) public void shouldNotCreateKeySelector(String expression, String expectedErrorMessage) { ExpressionException ee = assertThrows(ExpressionException.class, () -> keySelector(expression)); @@ -183,19 +189,19 @@ public void shouldNotCreateKeySelector(String expression, String expectedErrorMe useHeadersInDisplayName = true, textBlock = """ - ESPRESSION, EXPECTED_ERROR_MESSAGE - '', Expected the root token [VALUE] while evaluating [name] - invalidValue, Expected the root token [VALUE] while evaluating [name] - VALUE, Found the invalid expression [VALUE] while evaluating [name] - VALUE., Found the invalid expression [VALUE.] while evaluating [name] - VALUE.., Found the invalid expression [VALUE..] with missing tokens while evaluating [name] - VALUE.attrib[], Found the invalid indexed expression [VALUE.attrib[]] while evaluating [name] - VALUE.attrib[0]xsd, Found the invalid indexed expression [VALUE.attrib[0]xsd] while evaluating [name] - VALUE.attrib[], Found the invalid indexed expression [VALUE.attrib[]] while evaluating [name] - VALUE.attrib[a], Found the invalid indexed expression [VALUE.attrib[a]] while evaluating [name] - VALUE.attrib[a]., Found the invalid indexed expression [VALUE.attrib[a].] while evaluating [name] - VALUE.attrib[0]., Found the invalid indexed expression [VALUE.attrib[a].] while evaluating [name] - """) + ESPRESSION, EXPECTED_ERROR_MESSAGE + '', Expected the root token [VALUE] while evaluating [name] + invalidValue, Expected the root token [VALUE] while evaluating [name] + VALUE, Found the invalid expression [VALUE] while evaluating [name] + VALUE., Found the invalid expression [VALUE.] while evaluating [name] + VALUE.., Found the invalid expression [VALUE..] with missing tokens while evaluating [name] + VALUE.attrib[], Found the invalid indexed expression [VALUE.attrib[]] while evaluating [name] + VALUE.attrib[0]xsd, Found the invalid indexed expression [VALUE.attrib[0]xsd] while evaluating [name] + VALUE.attrib[], Found the invalid indexed expression [VALUE.attrib[]] while evaluating [name] + VALUE.attrib[a], Found the invalid indexed expression [VALUE.attrib[a]] while evaluating [name] + VALUE.attrib[a]., Found the invalid indexed expression [VALUE.attrib[a].] while evaluating [name] + VALUE.attrib[0]., Found the invalid indexed expression [VALUE.attrib[a].] while evaluating [name] + """) public void shouldNotCreateValueSelector(String expression, String expectedErrorMessage) { ExpressionException ee = assertThrows(ExpressionException.class, () -> valueSelector(expression)); diff --git a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/test_utils/JsonNodeProvider.java b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/test_utils/JsonNodeProvider.java index ee6bb5e8..91f79d21 100644 --- a/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/test_utils/JsonNodeProvider.java +++ b/kafka-connector/src/test/java/com/lightstreamer/kafka_connector/adapters/test_utils/JsonNodeProvider.java @@ -31,16 +31,16 @@ private JsonNodeProvider() {} public static JsonNode RECORD = new JsonNodeProvider().newNode(); private ObjectNode newNode() { - List parentJoeChildren = + List joeChildren = new ArrayList<>( List.of( new Value("alex"), new Value( "anna", List.of(new Value("gloria"), new Value("terence"))), new Value("serena"))); - parentJoeChildren.add(null); + joeChildren.add(null); - Value value = new Value("joe", parentJoeChildren); + Value value = new Value("joe", joeChildren); value.signature = new byte[] {97, 98, 99, 100}; ObjectNode node = new ObjectMapper().valueToTree(value); diff --git a/kafka-connector/src/test/resources/should-expand-items.csv b/kafka-connector/src/test/resources/should-expand-items.csv index 6e7212c4..363ba5c9 100644 --- a/kafka-connector/src/test/resources/should-expand-items.csv +++ b/kafka-connector/src/test/resources/should-expand-items.csv @@ -1,22 +1,22 @@ TEMPLATE | SUBCRIBING_ITEM | SHOULD_SUBSCRIBE | SHOULD_EXPAND -complex-item-#{keyName=KEY.name,name=VALUE.name,child=VALUE.children[0].name} | complex- | false | false -complex-item-#{keyName=KEY.name,name=VALUE.name,child=VALUE.children[0].name} | complex-item- | true | true -complex-item-#{keyName=KEY.name,name=VALUE.name,child=VALUE.children[0].name} | complex-item- | true | true -complex-item-#{keyName=KEY.name,name=VALUE.name,child=VALUE.children[0].name} | complex-item- | true | true +complex-item-#{keyName=KEY.name,name=VALUE.name,child=VALUE.children[0].name} | complex-[name=joe] | false | false +complex-item-#{keyName=KEY.name,name=VALUE.name,child=VALUE.children[0].name} | complex-item-[name=joe] | true | true +complex-item-#{keyName=KEY.name,name=VALUE.name,child=VALUE.children[0].name} | complex-item-[name=joe,child=alex] | true | true +complex-item-#{keyName=KEY.name,name=VALUE.name,child=VALUE.children[0].name} | complex-item-[child=alex] | true | true complex-item-#{keyName=KEY.name,name=VALUE.name,child=VALUE.children[0].name} | complex-item | true | true complex-item-#{keyName=KEY.name,name=VALUE.name,child=VALUE.children[0].name} | complex-item- | false | false -complex-item-#{keyName=KEY.name,name=VALUE.name,child=VALUE.children[0].name} | complex-item- | true | true -complex-item-#{keyName=KEY.name,name=VALUE.name,child=VALUE.children[0].name} | complex-item- | true | true -complex-item-#{keyName=KEY.name,child=VALUE.children[1].children[0].name} | complex-item- | true | true -complex-item-#{keyName=KEY.name,child=VALUE.children[1].children[1].name} | complex-item- | true | true -complex-item-#{keyName=KEY.name,child=VALUE.children[1].children[1].name} | complex-item- | true | false -complex-item-#{child=VALUE.children[1].children[1].name} | complex-item- | false | false -complex-item-#{child=VALUE.children[1].children[1].name} | complex-item- | true | true -item-#{ts=TIMESTAMP,partition=PARTITION} | item- | true | true -item-#{ts=TIMESTAMP,partition=PARTITION} | item- | true | true -item-#{ts=TIMESTAMP,partition=PARTITION} | item- | true | true -item-#{ts=TIMESTAMP,partition=PARTITION} | item- | true | false -item-#{ts=TIMESTAMP,partition=PARTITION} | item- | true | false +complex-item-#{keyName=KEY.name,name=VALUE.name,child=VALUE.children[0].name} | complex-item-[keyName=joe] | true | true +complex-item-#{keyName=KEY.name,name=VALUE.name,child=VALUE.children[0].name} | complex-item-[keyName=joe,child=alex] | true | true +complex-item-#{keyName=KEY.name,child=VALUE.children[1].children[0].name} | complex-item-[keyName=joe,child=gloria] | true | true +complex-item-#{keyName=KEY.name,child=VALUE.children[1].children[1].name} | complex-item-[keyName=joe,child=terence] | true | true +complex-item-#{keyName=KEY.name,child=VALUE.children[1].children[1].name} | complex-item-[keyName=joe,child=carol] | true | false +complex-item-#{child=VALUE.children[1].children[1].name} | complex-item-[keyName=joe,child=terence] | false | false +complex-item-#{child=VALUE.children[1].children[1].name} | complex-item-[child=terence] | true | true +item-#{ts=TIMESTAMP,partition=PARTITION} | item-[ts=-1] | true | true +item-#{ts=TIMESTAMP,partition=PARTITION} | item-[partition=150] | true | true +item-#{ts=TIMESTAMP,partition=PARTITION} | item-[partition=150,ts=-1] | true | true +item-#{ts=TIMESTAMP,partition=PARTITION} | item-[partition=150,ts=1] | true | false +item-#{ts=TIMESTAMP,partition=PARTITION} | item-[partition=50] | true | false item | item | true | true item-first | item-first | true | true item_123_ | item_123_ | true | true