Skip to content

Commit bfc4fdf

Browse files
l46kokcopybara-github
authored andcommitted
Refactor native extensions to separately hold type references
PiperOrigin-RevId: 915744276
1 parent 0837a51 commit bfc4fdf

1 file changed

Lines changed: 41 additions & 34 deletions

File tree

extensions/src/main/java/dev/cel/extensions/CelNativeTypesExtensions.java

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,12 @@ private static Optional<PropertyAccessor> buildPropertyAccessor(
356356
if (getter != null) {
357357
propType = getter.getReturnType();
358358
genericPropType = getter.getGenericReturnType();
359-
discoverCustomTypes(genericPropType, queue);
359+
queue.addAll(TypeReferenceCollector.collect(genericPropType));
360360
compiledGetter = compileGetter(getter);
361361
} else if (field != null) {
362362
propType = field.getType();
363363
genericPropType = field.getGenericType();
364-
discoverCustomTypes(genericPropType, queue);
364+
queue.addAll(TypeReferenceCollector.collect(genericPropType));
365365
compiledGetter = compileFieldGetter(field);
366366
}
367367

@@ -386,46 +386,53 @@ private static Optional<PropertyAccessor> buildPropertyAccessor(
386386

387387
/**
388388
* Recursively explores a {@link Type} and discovers any transitive, user-defined custom POJO
389-
* classes nested inside multi-level generic collections, lists, maps, or optionals, pushing
390-
* them into the scanning discovery queue.
389+
* classes nested inside multi-level generic collections, lists, maps, or optionals, collecting
390+
* them for subsequent properties discovery.
391391
*
392392
* <p>"Custom types" are any public non-primitive, non-built-in Java classes that require
393393
* explicit properties reflective scanning and mapping to a CEL StructType schema (as opposed to
394394
* standard built-in types like {@code String}, {@code List}, or {@code Map}).
395-
*
396-
* @param type The Java type token or parameterized collection type to recursively unpack.
397-
* @param queue The central scanning queue where newly discovered custom classes are pushed for
398-
* subsequent properties discovery.
399395
*/
400-
private static void discoverCustomTypes(Type type, Queue<Class<?>> queue) {
401-
Preconditions.checkNotNull(type, "Type to discover cannot be null.");
402-
Preconditions.checkNotNull(queue, "Queue cannot be null.");
403-
TypeToken<?> token = TypeToken.of(type);
404-
Class<?> rawType = token.getRawType();
405-
406-
if (List.class.isAssignableFrom(rawType)) {
407-
Type elementType = ReflectionUtil.resolveGenericParameter(token, List.class, 0);
408-
discoverCustomTypes(elementType, queue);
409-
return;
410-
}
396+
private static final class TypeReferenceCollector {
397+
private final Set<Class<?>> collectedTypes = new HashSet<>();
398+
399+
/**
400+
* Traverses the given type and returns an immutable set of all custom POJO classes found.
401+
*
402+
* @param type The Java type token or parameterized collection type to recursively unpack.
403+
*/
404+
private static ImmutableSet<Class<?>> collect(Type type) {
405+
TypeReferenceCollector collector = new TypeReferenceCollector();
406+
collector.discover(type);
407+
return ImmutableSet.copyOf(collector.collectedTypes);
408+
}
409+
410+
private void discover(Type type) {
411+
Preconditions.checkNotNull(type, "Type to discover cannot be null.");
412+
TypeToken<?> token = TypeToken.of(type);
413+
Class<?> rawType = token.getRawType();
414+
415+
if (List.class.isAssignableFrom(rawType)) {
416+
discover(ReflectionUtil.resolveGenericParameter(token, List.class, 0));
417+
return;
418+
}
411419

412-
if (Map.class.isAssignableFrom(rawType)) {
413-
Type keyType = ReflectionUtil.resolveGenericParameter(token, Map.class, 0);
414-
Type valueType = ReflectionUtil.resolveGenericParameter(token, Map.class, 1);
415-
discoverCustomTypes(keyType, queue);
416-
discoverCustomTypes(valueType, queue);
417-
return;
418-
}
420+
if (Map.class.isAssignableFrom(rawType)) {
421+
discover(ReflectionUtil.resolveGenericParameter(token, Map.class, 0));
422+
discover(ReflectionUtil.resolveGenericParameter(token, Map.class, 1));
423+
return;
424+
}
419425

420-
if (rawType == Optional.class) {
421-
Type optionalType = ReflectionUtil.resolveGenericParameter(token, Optional.class, 0);
422-
discoverCustomTypes(optionalType, queue);
423-
return;
424-
}
426+
if (rawType == Optional.class) {
427+
discover(ReflectionUtil.resolveGenericParameter(token, Optional.class, 0));
428+
return;
429+
}
425430

426-
if (!JAVA_TO_DEFAULT_VALUE_MAP.containsKey(rawType)
427-
&& Modifier.isPublic(rawType.getModifiers())) {
428-
queue.add(rawType);
431+
// Custom types are non-builtin, public classes
432+
if (!JAVA_TO_DEFAULT_VALUE_MAP.containsKey(rawType)
433+
&& Modifier.isPublic(rawType.getModifiers())) {
434+
collectedTypes.add(rawType);
435+
}
429436
}
430437
}
431438

0 commit comments

Comments
 (0)