Skip to content

Commit

Permalink
Create a separate interface for validating required fields in a builder
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 646658941
  • Loading branch information
l46kok authored and copybara-github committed Jul 2, 2024
1 parent 2478747 commit bf05e84
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 33 deletions.
13 changes: 13 additions & 0 deletions policy/src/main/java/dev/cel/policy/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ java_library(
tags = [
],
deps = [
":required_fields_checker",
":source",
"//:auto_value",
"@maven//:com_google_errorprone_error_prone_annotations",
Expand Down Expand Up @@ -89,6 +90,18 @@ java_library(
],
)

java_library(
name = "required_fields_checker",
srcs = [
"RequiredFieldsChecker.java",
],
visibility = ["//visibility:private"],
deps = [
"//:auto_value",
"@maven//:com_google_guava_guava",
],
)

java_library(
name = "parser_context",
srcs = [
Expand Down
56 changes: 23 additions & 33 deletions policy/src/main/java/dev/cel/policy/CelPolicyConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,12 @@
package dev.cel.policy;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.util.Arrays.stream;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.CheckReturnValue;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Optional;

Expand Down Expand Up @@ -108,7 +105,7 @@ public abstract static class VariableDecl {

/** Builder for {@link VariableDecl}. */
@AutoValue.Builder
public abstract static class Builder {
public abstract static class Builder implements RequiredFieldsChecker {

abstract Optional<String> name();

Expand All @@ -118,10 +115,10 @@ public abstract static class Builder {

public abstract Builder setType(TypeDecl typeDecl);

ImmutableList<String> getMissingRequiredFieldNames() {
return getMissingRequiredFields(
new AbstractMap.SimpleEntry<>("name", name()),
new AbstractMap.SimpleEntry<>("type", type()));
@Override
public ImmutableList<RequiredField> requiredFields() {
return ImmutableList.of(
RequiredField.of("name", this::name), RequiredField.of("type", this::type));
}

/** Builds a new instance of {@link VariableDecl}. */
Expand All @@ -148,7 +145,7 @@ public abstract static class FunctionDecl {

/** Builder for {@link FunctionDecl}. */
@AutoValue.Builder
public abstract static class Builder {
public abstract static class Builder implements RequiredFieldsChecker {

abstract Optional<String> name();

Expand All @@ -158,10 +155,10 @@ public abstract static class Builder {

public abstract Builder setOverloads(ImmutableSet<OverloadDecl> overloads);

ImmutableList<String> getMissingRequiredFieldNames() {
return getMissingRequiredFields(
new AbstractMap.SimpleEntry<>("name", name()),
new AbstractMap.SimpleEntry<>("overloads", overloads()));
@Override
public ImmutableList<RequiredField> requiredFields() {
return ImmutableList.of(
RequiredField.of("name", this::name), RequiredField.of("overloads", this::overloads));
}

/** Builds a new instance of {@link FunctionDecl}. */
Expand Down Expand Up @@ -200,7 +197,7 @@ public abstract static class OverloadDecl {

/** Builder for {@link OverloadDecl}. */
@AutoValue.Builder
public abstract static class Builder {
public abstract static class Builder implements RequiredFieldsChecker {

abstract Optional<String> id();

Expand Down Expand Up @@ -228,10 +225,10 @@ public Builder addArguments(TypeDecl... args) {

public abstract Builder setReturnType(TypeDecl returnType);

ImmutableList<String> getMissingRequiredFieldNames() {
return getMissingRequiredFields(
new AbstractMap.SimpleEntry<>("id", id()),
new AbstractMap.SimpleEntry<>("return", returnType()));
@Override
public ImmutableList<RequiredField> requiredFields() {
return ImmutableList.of(
RequiredField.of("id", this::id), RequiredField.of("return", this::returnType));
}

/** Builds a new instance of {@link OverloadDecl}. */
Expand Down Expand Up @@ -259,7 +256,7 @@ public abstract static class TypeDecl {

/** Builder for {@link TypeDecl}. */
@AutoValue.Builder
public abstract static class Builder {
public abstract static class Builder implements RequiredFieldsChecker {

abstract Optional<String> name();

Expand All @@ -283,8 +280,9 @@ public Builder addParams(Iterable<TypeDecl> params) {

public abstract Builder setIsTypeParam(boolean isTypeParam);

ImmutableList<String> getMissingRequiredFieldNames() {
return getMissingRequiredFields(new AbstractMap.SimpleEntry<>("type_name", name()));
@Override
public ImmutableList<RequiredField> requiredFields() {
return ImmutableList.of(RequiredField.of("type_name", this::name));
}

@CheckReturnValue
Expand Down Expand Up @@ -319,7 +317,7 @@ public abstract static class ExtensionConfig {

/** Builder for {@link ExtensionConfig}. */
@AutoValue.Builder
public abstract static class Builder {
public abstract static class Builder implements RequiredFieldsChecker {

abstract Optional<String> name();

Expand All @@ -329,8 +327,9 @@ public abstract static class Builder {

public abstract Builder setVersion(Integer version);

ImmutableList<String> getMissingRequiredFieldNames() {
return getMissingRequiredFields(new AbstractMap.SimpleEntry<>("name", name()));
@Override
public ImmutableList<RequiredField> requiredFields() {
return ImmutableList.of(RequiredField.of("name", this::name));
}

/** Builds a new instance of {@link ExtensionConfig}. */
Expand All @@ -352,13 +351,4 @@ public static ExtensionConfig of(String name, int version) {
return newBuilder().setName(name).setVersion(version).build();
}
}

@SafeVarargs
private static ImmutableList<String> getMissingRequiredFields(
AbstractMap.SimpleEntry<String, Optional<?>>... requiredFields) {
return stream(requiredFields)
.filter(entry -> !entry.getValue().isPresent())
.map(AbstractMap.SimpleEntry::getKey)
.collect(toImmutableList());
}
}
49 changes: 49 additions & 0 deletions policy/src/main/java/dev/cel/policy/RequiredFieldsChecker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package dev.cel.policy;

import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import java.util.Optional;
import java.util.function.Supplier;

/**
* Interface to be implemented on a builder that can be used to verify all required fields being
* set.
*/
interface RequiredFieldsChecker {

ImmutableList<RequiredField> requiredFields();

default ImmutableList<String> getMissingRequiredFieldNames() {
return requiredFields().stream()
.filter(entry -> !entry.fieldValue().get().isPresent())
.map(RequiredField::displayName)
.collect(toImmutableList());
}

@AutoValue
abstract class RequiredField {
abstract String displayName();

abstract Supplier<Optional<?>> fieldValue();

static RequiredField of(String displayName, Supplier<Optional<?>> fieldValue) {
return new AutoValue_RequiredFieldsChecker_RequiredField(displayName, fieldValue);
}
}
}

0 comments on commit bf05e84

Please sign in to comment.