This is an automated email from the ASF dual-hosted git repository.
chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git
The following commit(s) were added to refs/heads/main by this push:
new 73b62f9d feat(java): array row encoder supports set of interface type
(#2333)
73b62f9d is described below
commit 73b62f9d3c62602aea5033bfe65d8dfb20f39c25
Author: Steven Schlansker <[email protected]>
AuthorDate: Thu Jun 12 20:41:03 2025 -0700
feat(java): array row encoder supports set of interface type (#2333)
## What does this PR do?
improve array row encoder to support custom collections that are not
List, for example TreeSet
also supports interface types as value
Co-authored-by: Shawn Yang <[email protected]>
---
.../main/java/org/apache/fory/type/TypeUtils.java | 9 ++++-
.../fory/format/encoder/ArrayEncoderBuilder.java | 3 +-
.../org/apache/fory/format/encoder/Encoders.java | 13 ++++---
.../format/encoder/ImplementInterfaceTest.java | 40 ++++++++++++++++++++++
4 files changed, 58 insertions(+), 7 deletions(-)
diff --git a/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java
b/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java
index 1c7b3946..6bc0b4b0 100644
--- a/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java
+++ b/java/fory-core/src/main/java/org/apache/fory/type/TypeUtils.java
@@ -599,7 +599,8 @@ public class TypeUtils {
public static boolean isBean(TypeRef<?> typeRef, TypeResolutionContext ctx) {
Class<?> cls = getRawType(typeRef);
- if (ctx.isSynthesizeInterfaces() && (RecordUtils.isRecord(cls) ||
(cls.isInterface()))) {
+ if (ctx.isSynthesizeInterfaces()
+ && (RecordUtils.isRecord(cls) || isSynthesizableInterface(cls))) {
return true;
}
if (Modifier.isAbstract(cls.getModifiers()) ||
Modifier.isInterface(cls.getModifiers())) {
@@ -651,6 +652,12 @@ public class TypeUtils {
}
}
+ private static boolean isSynthesizableInterface(Class<?> cls) {
+ return cls.isInterface()
+ && !Collection.class.isAssignableFrom(cls)
+ && !Map.class.isAssignableFrom(cls);
+ }
+
/** Check if <code>typeToken</code> is supported by row-format. */
public static boolean isSupported(TypeRef<?> typeRef) {
return isSupported(typeRef, new
TypeResolutionContext(CustomTypeRegistry.EMPTY));
diff --git
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/ArrayEncoderBuilder.java
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/ArrayEncoderBuilder.java
index 8937a66e..2865d62c 100644
---
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/ArrayEncoderBuilder.java
+++
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/ArrayEncoderBuilder.java
@@ -142,7 +142,8 @@ public class ArrayEncoderBuilder extends
BaseBinaryEncoderBuilder {
Expression.Reference inputObject =
new Expression.Reference(ROOT_OBJECT_NAME, TypeUtils.COLLECTION_TYPE,
false);
Expression.Cast array =
- new Expression.Cast(inputObject, arrayToken,
ctx.newName(getRawType(arrayToken)));
+ new Expression.Cast(
+ inputObject, arrayToken, ctx.newName(getRawType(arrayToken)),
false, false);
expressions.add(array);
Expression.Reference fieldExpr = new Expression.Reference(FIELD_NAME,
ARROW_FIELD_TYPE, false);
diff --git
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/Encoders.java
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/Encoders.java
index 020167f6..18845507 100644
---
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/Encoders.java
+++
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/Encoders.java
@@ -343,7 +343,7 @@ public class Encoders {
Class<? extends Collection> arrayCls, Class<B> elementType) {
Preconditions.checkNotNull(elementType);
- return (ArrayEncoder<T>) arrayEncoder(TypeUtils.listOf(elementType), null);
+ return (ArrayEncoder<T>) arrayEncoder(TypeUtils.collectionOf(elementType),
null);
}
/**
@@ -581,7 +581,8 @@ public class Encoders {
private static Set<TypeRef<?>> beanSet(TypeRef<?> token) {
Set<TypeRef<?>> set = new HashSet<>();
- if (TypeUtils.isBean(token)) {
+ if (TypeUtils.isBean(
+ token, new
TypeResolutionContext(CustomTypeEncoderRegistry.customTypeHandler(), true))) {
set.add(token);
return set;
}
@@ -645,6 +646,8 @@ public class Encoders {
}
private static void findBeanToken(TypeRef<?> typeRef,
java.util.Set<TypeRef<?>> set) {
+ TypeResolutionContext typeCtx =
+ new
TypeResolutionContext(CustomTypeEncoderRegistry.customTypeHandler(), true);
Set<TypeRef<?>> visited = new LinkedHashSet<>();
while (TypeUtils.ITERABLE_TYPE.isSupertypeOf(typeRef)
|| TypeUtils.MAP_TYPE.isSupertypeOf(typeRef)) {
@@ -654,20 +657,20 @@ public class Encoders {
visited.add(typeRef);
if (TypeUtils.ITERABLE_TYPE.isSupertypeOf(typeRef)) {
typeRef = TypeUtils.getElementType(typeRef);
- if (TypeUtils.isBean(typeRef)) {
+ if (TypeUtils.isBean(typeRef, typeCtx)) {
set.add(typeRef);
}
findBeanToken(typeRef, set);
} else {
Tuple2<TypeRef<?>, TypeRef<?>> tuple2 =
TypeUtils.getMapKeyValueType(typeRef);
- if (TypeUtils.isBean(tuple2.f0)) {
+ if (TypeUtils.isBean(tuple2.f0, typeCtx)) {
set.add(tuple2.f0);
} else {
typeRef = tuple2.f0;
findBeanToken(tuple2.f0, set);
}
- if (TypeUtils.isBean(tuple2.f1)) {
+ if (TypeUtils.isBean(tuple2.f1, typeCtx)) {
set.add(tuple2.f1);
} else {
typeRef = tuple2.f1;
diff --git
a/java/fory-format/src/test/java/org/apache/fory/format/encoder/ImplementInterfaceTest.java
b/java/fory-format/src/test/java/org/apache/fory/format/encoder/ImplementInterfaceTest.java
index 82d6284c..67047d3f 100644
---
a/java/fory-format/src/test/java/org/apache/fory/format/encoder/ImplementInterfaceTest.java
+++
b/java/fory-format/src/test/java/org/apache/fory/format/encoder/ImplementInterfaceTest.java
@@ -22,11 +22,14 @@ package org.apache.fory.format.encoder;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
+import java.util.TreeSet;
import lombok.Data;
import org.apache.fory.annotation.ForyField;
+import org.apache.fory.format.row.binary.BinaryArray;
import org.apache.fory.format.row.binary.BinaryRow;
import org.apache.fory.memory.MemoryBuffer;
import org.apache.fory.memory.MemoryUtils;
+import org.apache.fory.reflect.TypeRef;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -258,4 +261,41 @@ public class ImplementInterfaceTest {
final ListOuter deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean.f1().get(0).f1(), 42);
}
+
+ public interface Value extends Comparable<Value> {
+ int v();
+
+ @Override
+ default int compareTo(final Value o) {
+ return Integer.compare(v(), o.v());
+ }
+ }
+
+ public static class ValueImpl implements Value {
+ int v;
+
+ public ValueImpl(final int v) {
+ this.v = v;
+ }
+
+ @Override
+ public int v() {
+ return v;
+ }
+ }
+
+ @Test
+ public void testTreeSetOfInterface() {
+ final ArrayEncoder<TreeSet<Value>> encoder =
+ Encoders.arrayEncoder(new TypeRef<TreeSet<Value>>() {});
+ final TreeSet<Value> expected = new TreeSet<Value>();
+ expected.add(new ValueImpl(1));
+ expected.add(new ValueImpl(3));
+ expected.add(new ValueImpl(5));
+ final BinaryArray array = encoder.toArray(expected);
+ final MemoryBuffer buffer = array.getBuffer();
+ array.pointTo(buffer, 0, buffer.size());
+ final TreeSet<Value> deserializedBean = encoder.fromArray(array);
+ Assert.assertEquals(deserializedBean, expected);
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]