Skip to content

Commit ca93bd0

Browse files
committed
feat: extend smt to support key/value/raw types
1 parent 2eb9477 commit ca93bd0

File tree

2 files changed

+58
-23
lines changed

2 files changed

+58
-23
lines changed

src/main/java/io/aiven/kafka/connect/transforms/FilterByFieldValue.java

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
import static org.apache.kafka.connect.data.Schema.Type.STRING;
3636

37-
public class FilterByFieldValue<R extends ConnectRecord<R>> implements Transformation<R> {
37+
public abstract class FilterByFieldValue<R extends ConnectRecord<R>> implements Transformation<R> {
3838

3939
private String fieldName;
4040
private Optional<String> fieldExpectedValue;
@@ -43,15 +43,23 @@ public class FilterByFieldValue<R extends ConnectRecord<R>> implements Transform
4343

4444
@Override
4545
public R apply(final R record) {
46-
if (record.value() instanceof Struct) {
47-
return handleStruct(record);
48-
} else if (record.value() instanceof Map) {
49-
return handleMap(record);
46+
if (operatingValue(record) == null) {
47+
return record;
48+
}
49+
50+
if (operatingSchema(record) == null) {
51+
return applySchemaless(record);
52+
} else {
53+
return applyWithSchema(record);
5054
}
51-
return record; // if record is other than map or struct, pass-by
5255
}
5356

54-
private R handleStruct(final R record) {
57+
58+
protected abstract Schema operatingSchema(R record);
59+
60+
protected abstract Object operatingValue(R record);
61+
62+
private R applyWithSchema(final R record) {
5563
final Struct struct = (Struct) record.value();
5664
final Optional<String> fieldValue = extractStructFieldValue(struct, fieldName);
5765
return filterCondition.test(fieldValue) ? record : null;
@@ -72,19 +80,19 @@ private Optional<String> extractStructFieldValue(final Struct struct, final Stri
7280
}
7381

7482
@SuppressWarnings("unchecked")
75-
private R handleMap(final R record) {
76-
final Map<String, Object> map = (Map<String, Object>) record.value();
77-
final Optional<String> fieldValue = extractMapFieldValue(map, fieldName);
78-
return filterCondition.test(fieldValue) ? record : null;
79-
}
80-
81-
private Optional<String> extractMapFieldValue(final Map<String, Object> map, final String fieldName) {
82-
if (!map.containsKey(fieldName)) {
83-
return Optional.empty();
83+
private R applySchemaless(final R record) {
84+
if (fieldName.isEmpty()) {
85+
final Optional<String> value = extractSchemalessFieldValue(operatingValue(record));
86+
return filterCondition.test(value) ? record : null;
87+
} else {
88+
final Map<String, Object> map = (Map<String, Object>) record.value();
89+
final Optional<String> fieldValue = extractSchemalessFieldValue(map.get(fieldName));
90+
return filterCondition.test(fieldValue) ? record : null;
8491
}
92+
}
8593

86-
final Object fieldValue = map.get(fieldName);
87-
94+
private Optional<String> extractSchemalessFieldValue(final Object fieldValue) {
95+
if (fieldValue == null) return Optional.empty();
8896
Optional<String> text = Optional.empty();
8997
if (isSupportedType(fieldValue)) {
9098
text = Optional.of(fieldValue.toString());
@@ -150,4 +158,31 @@ public void configure(final Map<String, ?> configs) {
150158
? matchCondition
151159
: (result -> !matchCondition.test(result));
152160
}
161+
162+
163+
public static final class Key<R extends ConnectRecord<R>> extends FilterByFieldValue<R> {
164+
165+
@Override
166+
protected Schema operatingSchema(R record) {
167+
return record.keySchema();
168+
}
169+
170+
@Override
171+
protected Object operatingValue(R record) {
172+
return record.key();
173+
}
174+
}
175+
176+
public static final class Value<R extends ConnectRecord<R>> extends FilterByFieldValue<R> {
177+
178+
@Override
179+
protected Schema operatingSchema(R record) {
180+
return record.valueSchema();
181+
}
182+
183+
@Override
184+
protected Object operatingValue(R record) {
185+
return record.value();
186+
}
187+
}
153188
}

src/test/java/io/aiven/kafka/connect/transforms/FilterByFieldValueTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class FilterByFieldValueTest {
4545

4646
@Test
4747
void shouldFilterOutRecordsEqualsToReadEvents() {
48-
final FilterByFieldValue<SourceRecord> filter = new FilterByFieldValue<>();
48+
final FilterByFieldValue<SourceRecord> filter = new FilterByFieldValue.Value<>();
4949
filter.configure(Map.of(
5050
"field.name", "op",
5151
"field.value", "r",
@@ -72,7 +72,7 @@ final var record = new SourceRecord(null, null, "some_topic", VALUE_SCHEMA, valu
7272

7373
@Test
7474
void shouldKeepRecordsNotEqualsToReadEvents() {
75-
final FilterByFieldValue<SourceRecord> filter = new FilterByFieldValue<>();
75+
final FilterByFieldValue<SourceRecord> filter = new FilterByFieldValue.Value<>();
7676
filter.configure(Map.of(
7777
"field.name", "op",
7878
"field.value", "r",
@@ -99,7 +99,7 @@ final var record = new SourceRecord(null, null, "some_topic", VALUE_SCHEMA, valu
9999

100100
@Test
101101
void shouldFilterOutRecordsNotEqualsReadEvents() {
102-
final FilterByFieldValue<SourceRecord> filter = new FilterByFieldValue<>();
102+
final FilterByFieldValue<SourceRecord> filter = new FilterByFieldValue.Value<>();
103103
filter.configure(Map.of(
104104
"field.name", "op",
105105
"field.value", "r",
@@ -126,7 +126,7 @@ final var record = new SourceRecord(null, null, "some_topic", VALUE_SCHEMA, valu
126126

127127
@Test
128128
void shouldFilterOutMapFieldValue() {
129-
final FilterByFieldValue<SourceRecord> filterByFieldValue = new FilterByFieldValue<>();
129+
final FilterByFieldValue<SourceRecord> filterByFieldValue = new FilterByFieldValue.Value<>();
130130
final Map<String, String> configs = new HashMap<>();
131131
configs.put("field.name", "language");
132132
configs.put("field.value.pattern", ".*Java.*");
@@ -137,7 +137,7 @@ void shouldFilterOutMapFieldValue() {
137137
value.put("name", "John Doe");
138138
value.put("language", "Java");
139139

140-
final var record = new SourceRecord(null, null, "some_topic", Schema.STRING_SCHEMA, value);
140+
final var record = new SourceRecord(null, null, "some_topic", null, value);
141141

142142
final var actual = filterByFieldValue.apply(record);
143143
assertNull(actual, "The record should be filtered out");

0 commit comments

Comments
 (0)