Skip to content

Commit 8d2c7e3

Browse files
l46kokcopybara-github
authored andcommitted
Add BaseProtoMessageValueProvider to decouple full/lite protobuf value providers
PiperOrigin-RevId: 752895239
1 parent 5a9d46e commit 8d2c7e3

18 files changed

+294
-108
lines changed

common/src/main/java/dev/cel/common/values/BUILD.bazel

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,32 @@ cel_android_library(
8989
],
9090
)
9191

92+
java_library(
93+
name = "combined_cel_value_provider",
94+
srcs = ["CombinedCelValueProvider.java"],
95+
tags = [
96+
],
97+
deps = [
98+
"//common/values:cel_value",
99+
"//common/values:cel_value_provider",
100+
"@maven//:com_google_errorprone_error_prone_annotations",
101+
"@maven//:com_google_guava_guava",
102+
],
103+
)
104+
105+
cel_android_library(
106+
name = "combined_cel_value_provider_android",
107+
srcs = ["CombinedCelValueProvider.java"],
108+
tags = [
109+
],
110+
deps = [
111+
":cel_value_android",
112+
"//common/values:cel_value_provider_android",
113+
"@maven//:com_google_errorprone_error_prone_annotations",
114+
"@maven_android//:com_google_guava_guava",
115+
],
116+
)
117+
92118
java_library(
93119
name = "values",
94120
srcs = CEL_VALUES_SOURCES,
@@ -207,14 +233,13 @@ java_library(
207233
tags = [
208234
],
209235
deps = [
236+
":base_proto_message_value_provider",
210237
":cel_value",
211-
":cel_value_provider",
212238
":proto_message_value",
213-
"//common:error_codes",
214-
"//common:runtime_exception",
215239
"//common/annotations",
216240
"//common/internal:dynamic_proto",
217241
"//common/internal:proto_message_factory",
242+
"//common/values:base_proto_cel_value_converter",
218243
"@maven//:com_google_errorprone_error_prone_annotations",
219244
"@maven//:com_google_protobuf_protobuf_java",
220245
],
@@ -280,11 +305,12 @@ java_library(
280305
tags = [
281306
],
282307
deps = [
308+
":base_proto_message_value_provider",
283309
":cel_value",
284-
":cel_value_provider",
285310
":proto_message_lite_value",
286311
"//common/internal:cel_lite_descriptor_pool",
287312
"//common/internal:default_lite_descriptor_pool",
313+
"//common/values:base_proto_cel_value_converter",
288314
"//protobuf:cel_lite_descriptor",
289315
"@maven//:com_google_errorprone_error_prone_annotations",
290316
"@maven//:com_google_guava_guava",
@@ -298,14 +324,41 @@ cel_android_library(
298324
tags = [
299325
],
300326
deps = [
327+
":base_proto_message_value_provider_android",
301328
":cel_value_android",
302-
":cel_value_provider_android",
303329
":proto_message_lite_value_android",
304330
"//common/internal:cel_lite_descriptor_pool_android",
305331
"//common/internal:default_lite_descriptor_pool_android",
332+
"//common/values:base_proto_cel_value_converter_android",
306333
"//protobuf:cel_lite_descriptor",
307334
"@maven//:com_google_errorprone_error_prone_annotations",
308335
"@maven_android//:com_google_guava_guava",
309336
"@maven_android//:com_google_protobuf_protobuf_javalite",
310337
],
311338
)
339+
340+
java_library(
341+
name = "base_proto_message_value_provider",
342+
srcs = ["BaseProtoMessageValueProvider.java"],
343+
tags = [
344+
],
345+
deps = [
346+
"//common/annotations",
347+
"//common/values:base_proto_cel_value_converter",
348+
"//common/values:cel_value_provider",
349+
"@maven//:com_google_errorprone_error_prone_annotations",
350+
],
351+
)
352+
353+
cel_android_library(
354+
name = "base_proto_message_value_provider_android",
355+
srcs = ["BaseProtoMessageValueProvider.java"],
356+
tags = [
357+
],
358+
deps = [
359+
"//common/annotations",
360+
"//common/values:base_proto_cel_value_converter_android",
361+
"//common/values:cel_value_provider_android",
362+
"@maven//:com_google_errorprone_error_prone_annotations",
363+
],
364+
)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package dev.cel.common.values;
16+
17+
import com.google.errorprone.annotations.Immutable;
18+
import dev.cel.common.annotations.Internal;
19+
20+
/**
21+
* {@code BaseProtoMessageValueProvider} is a common parent to {@code ProtoMessageValueProvider} and
22+
* {@code ProtoMessageLiteValueProvider}.
23+
*
24+
* <p>CEL-Java internals. Do not use. Use one of the inherited variants mentioned above.
25+
*/
26+
@Internal
27+
@Immutable
28+
public abstract class BaseProtoMessageValueProvider implements CelValueProvider {
29+
30+
public abstract BaseProtoCelValueConverter protoCelValueConverter();
31+
}

common/src/main/java/dev/cel/common/values/CelValueConverter.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.google.common.collect.ImmutableList;
1919
import com.google.common.collect.ImmutableMap;
2020
import com.google.common.primitives.UnsignedLong;
21+
import com.google.errorprone.annotations.Immutable;
2122
import dev.cel.common.annotations.Internal;
2223
import java.util.Map;
2324
import java.util.Map.Entry;
@@ -31,6 +32,7 @@
3132
*/
3233
@SuppressWarnings("unchecked") // Unchecked cast of generics due to type-erasure (ex: MapValue).
3334
@Internal
35+
@Immutable
3436
abstract class CelValueConverter {
3537

3638
/** Adapts a {@link CelValue} to a plain old Java Object. */

common/src/main/java/dev/cel/common/values/CelValueProvider.java

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414

1515
package dev.cel.common.values;
1616

17-
import com.google.common.base.Preconditions;
18-
import com.google.common.collect.ImmutableList;
1917
import com.google.errorprone.annotations.Immutable;
2018
import java.util.Map;
2119
import java.util.Optional;
@@ -31,32 +29,4 @@ public interface CelValueProvider {
3129
* special cases such as wrappers where its primitive is returned.
3230
*/
3331
Optional<CelValue> newValue(String structType, Map<String, Object> fields);
34-
35-
/**
36-
* The {@link CombinedCelValueProvider} takes one or more {@link CelValueProvider} instances and
37-
* attempts to create a {@link CelValue} instance for a given struct type name by calling each
38-
* value provider in the order that they are provided to the constructor.
39-
*/
40-
@Immutable
41-
final class CombinedCelValueProvider implements CelValueProvider {
42-
private final ImmutableList<CelValueProvider> celValueProviders;
43-
44-
public CombinedCelValueProvider(CelValueProvider first, CelValueProvider second) {
45-
Preconditions.checkNotNull(first);
46-
Preconditions.checkNotNull(second);
47-
celValueProviders = ImmutableList.of(first, second);
48-
}
49-
50-
@Override
51-
public Optional<CelValue> newValue(String structType, Map<String, Object> fields) {
52-
for (CelValueProvider provider : celValueProviders) {
53-
Optional<CelValue> newValue = provider.newValue(structType, fields);
54-
if (newValue.isPresent()) {
55-
return newValue;
56-
}
57-
}
58-
59-
return Optional.empty();
60-
}
61-
}
6232
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package dev.cel.common.values;
16+
17+
import static com.google.common.base.Preconditions.checkArgument;
18+
import static com.google.common.base.Preconditions.checkNotNull;
19+
20+
import com.google.common.collect.ImmutableList;
21+
import com.google.errorprone.annotations.Immutable;
22+
import java.util.Map;
23+
import java.util.Optional;
24+
25+
/**
26+
* The {@link CombinedCelValueProvider} takes one or more {@link CelValueProvider} instances and
27+
* attempts to create a {@link CelValue} instance for a given struct type name by calling each value
28+
* provider in the order that they are provided to the constructor.
29+
*/
30+
@Immutable
31+
public final class CombinedCelValueProvider implements CelValueProvider {
32+
private final ImmutableList<CelValueProvider> celValueProviders;
33+
34+
/** Combines the provided first and second {@link CelValueProvider}. */
35+
public static CombinedCelValueProvider combine(CelValueProvider... providers) {
36+
checkArgument(providers.length >= 2, "You must provide two or more providers");
37+
return new CombinedCelValueProvider(ImmutableList.copyOf(providers));
38+
}
39+
40+
@Override
41+
public Optional<CelValue> newValue(String structType, Map<String, Object> fields) {
42+
for (CelValueProvider provider : celValueProviders) {
43+
Optional<CelValue> newValue = provider.newValue(structType, fields);
44+
if (newValue.isPresent()) {
45+
return newValue;
46+
}
47+
}
48+
49+
return Optional.empty();
50+
}
51+
52+
/** Returns the underlying {@link CelValueProvider}s in order. */
53+
public ImmutableList<CelValueProvider> valueProviders() {
54+
return celValueProviders;
55+
}
56+
57+
private CombinedCelValueProvider(ImmutableList<CelValueProvider> providers) {
58+
celValueProviders = checkNotNull(providers);
59+
}
60+
}

common/src/main/java/dev/cel/common/values/ProtoMessageLiteValueProvider.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@
3030
* fully qualified name and its fields to populate.
3131
*/
3232
@Immutable
33-
public class ProtoMessageLiteValueProvider implements CelValueProvider {
33+
public class ProtoMessageLiteValueProvider extends BaseProtoMessageValueProvider {
3434
private final CelLiteDescriptorPool descriptorPool;
3535
private final ProtoLiteCelValueConverter protoLiteCelValueConverter;
3636

37-
public ProtoLiteCelValueConverter getProtoLiteCelValueConverter() {
37+
@Override
38+
public BaseProtoCelValueConverter protoCelValueConverter() {
3839
return protoLiteCelValueConverter;
3940
}
4041

common/src/main/java/dev/cel/common/values/ProtoMessageValueProvider.java

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
import com.google.protobuf.Descriptors.Descriptor;
1919
import com.google.protobuf.Descriptors.FieldDescriptor;
2020
import com.google.protobuf.Message;
21-
import dev.cel.common.CelErrorCode;
22-
import dev.cel.common.CelRuntimeException;
2321
import dev.cel.common.annotations.Internal;
2422
import dev.cel.common.internal.DynamicProto;
2523
import dev.cel.common.internal.ProtoAdapter;
@@ -35,19 +33,23 @@
3533
*/
3634
@Immutable
3735
@Internal
38-
public class ProtoMessageValueProvider implements CelValueProvider {
36+
public class ProtoMessageValueProvider extends BaseProtoMessageValueProvider {
3937
private final ProtoAdapter protoAdapter;
4038
private final ProtoMessageFactory protoMessageFactory;
4139
private final ProtoCelValueConverter protoCelValueConverter;
4240

43-
public ProtoCelValueConverter getProtoCelValueConverter() {
41+
@Override
42+
public BaseProtoCelValueConverter protoCelValueConverter() {
4443
return protoCelValueConverter;
4544
}
4645

4746
@Override
4847
public Optional<CelValue> newValue(String structType, Map<String, Object> fields) {
48+
Message.Builder builder = protoMessageFactory.newBuilder(structType).orElse(null);
49+
if (builder == null) {
50+
return Optional.empty();
51+
}
4952
try {
50-
Message.Builder builder = getMessageBuilderOrThrow(structType);
5153
Descriptor descriptor = builder.getDescriptorForType();
5254
for (Map.Entry<String, Object> entry : fields.entrySet()) {
5355
FieldDescriptor fieldDescriptor = findField(descriptor, entry.getKey());
@@ -63,17 +65,6 @@ public Optional<CelValue> newValue(String structType, Map<String, Object> fields
6365
}
6466
}
6567

66-
private Message.Builder getMessageBuilderOrThrow(String messageName) {
67-
return protoMessageFactory
68-
.newBuilder(messageName)
69-
.orElseThrow(
70-
() ->
71-
new CelRuntimeException(
72-
new IllegalArgumentException(
73-
String.format("cannot resolve '%s' as a message", messageName)),
74-
CelErrorCode.ATTRIBUTE_NOT_FOUND));
75-
}
76-
7768
private FieldDescriptor findField(Descriptor descriptor, String fieldName) {
7869
FieldDescriptor fieldDescriptor = descriptor.findFieldByName(fieldName);
7970
if (fieldDescriptor != null) {

common/src/test/java/dev/cel/common/values/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ java_library(
2828
"//common/values:cel_byte_string",
2929
"//common/values:cel_value",
3030
"//common/values:cel_value_provider",
31+
"//common/values:combined_cel_value_provider",
3132
"//common/values:proto_message_lite_value",
3233
"//common/values:proto_message_lite_value_provider",
3334
"//common/values:proto_message_value",

common/src/test/java/dev/cel/common/values/ProtoMessageLiteValueProviderTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,6 @@ public void newValue_emptyFields_success() {
4949

5050
@Test
5151
public void getProtoLiteCelValueConverter() {
52-
assertThat(VALUE_PROVIDER.getProtoLiteCelValueConverter()).isNotNull();
52+
assertThat(VALUE_PROVIDER.protoCelValueConverter()).isNotNull();
5353
}
5454
}

common/src/test/java/dev/cel/common/values/ProtoMessageValueProviderTest.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,12 @@
2222
import com.google.common.primitives.UnsignedLong;
2323
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
2424
import dev.cel.common.CelDescriptorUtil;
25-
import dev.cel.common.CelRuntimeException;
2625
import dev.cel.common.internal.CelDescriptorPool;
2726
import dev.cel.common.internal.DefaultDescriptorPool;
2827
import dev.cel.common.internal.DefaultMessageFactory;
2928
import dev.cel.common.internal.DynamicProto;
3029
import dev.cel.common.internal.ProtoMessageFactory;
3130
import dev.cel.common.internal.ProtoTimeUtils;
32-
import dev.cel.common.values.CelValueProvider.CombinedCelValueProvider;
3331
import dev.cel.expr.conformance.proto2.TestAllTypes;
3432
import dev.cel.expr.conformance.proto2.TestAllTypesExtensions;
3533
import java.time.Duration;
@@ -206,18 +204,11 @@ public void newValue_createProtoMessage_extensionFieldsPopulated() {
206204
}
207205

208206
@Test
209-
public void newValue_invalidMessageName_throws() {
207+
public void newValue_invalidMessageName_returnsEmpty() {
210208
ProtoMessageValueProvider protoMessageValueProvider =
211209
ProtoMessageValueProvider.newInstance(DYNAMIC_PROTO);
212210

213-
CelRuntimeException e =
214-
assertThrows(
215-
CelRuntimeException.class,
216-
() -> protoMessageValueProvider.newValue("bogus", ImmutableMap.of()));
217-
218-
assertThat(e)
219-
.hasMessageThat()
220-
.isEqualTo("java.lang.IllegalArgumentException: cannot resolve 'bogus' as a message");
211+
assertThat(protoMessageValueProvider.newValue("bogus", ImmutableMap.of())).isEmpty();
221212
}
222213

223214
@Test
@@ -245,7 +236,7 @@ public void newValue_onCombinedProvider() {
245236
ProtoMessageValueProvider protoMessageValueProvider =
246237
ProtoMessageValueProvider.newInstance(DYNAMIC_PROTO);
247238
CelValueProvider combinedProvider =
248-
new CombinedCelValueProvider(celValueProvider, protoMessageValueProvider);
239+
CombinedCelValueProvider.combine(celValueProvider, protoMessageValueProvider);
249240

250241
ProtoMessageValue protoMessageValue =
251242
(ProtoMessageValue)

0 commit comments

Comments
 (0)