dev.cel.runtime.UnknownContext Maven / Gradle / Ivy
// Copyright 2022 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.runtime;
import static com.google.common.collect.ImmutableList.toImmutableList;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.errorprone.annotations.Immutable;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
/**
* AsyncContext represents the state required for an iterative evaluation session in the CEL
* evaluator.
*
* It manages the effective state for an evaluation pass in {@link
* CelRuntime.Program#advanceEvaluation(UnknownContext)}.
*
*
This class is conditionally thread-safe.
*
*
* - Resolved values are type-erased, but must be immutable for this class to remain thread
* safe.
*
- The class implementing the variable resolver interface must be thread-safe.
*
*/
@Immutable
public class UnknownContext {
private final ImmutableList unresolvedAttributes;
// GlobalResolver implementation must be Immutable if used in this class.
@SuppressWarnings("Immutable")
private final GlobalResolver variableResolver;
// Clients must resolve attributes to Immutable types.
@SuppressWarnings("Immutable")
private final ImmutableMap resolvedAttributes;
private UnknownContext(
GlobalResolver resolver,
ImmutableList unresolvedAttributes,
ImmutableMap resolvedAttributes) {
this.unresolvedAttributes = unresolvedAttributes;
variableResolver = resolver;
this.resolvedAttributes = resolvedAttributes;
}
/**
* Creates a trivial unknown context from a GlobalResolver.
*
* This is used for compatibility with {@link CelRuntime.Program} overloads that don't specify
* any attributes.
*/
public static UnknownContext create(GlobalResolver resolver) {
return new UnknownContext(resolver, ImmutableList.of(), ImmutableMap.of());
}
/** Creates an unknown context from a list */
public static UnknownContext create(
CelVariableResolver resolver, Collection attributes) {
return new UnknownContext(
createExprVariableResolver(resolver), ImmutableList.copyOf(attributes), ImmutableMap.of());
}
/** Adapts a CelVariableResolver to the legacy impl equivalent GlobalResolver. */
private static GlobalResolver createExprVariableResolver(CelVariableResolver resolver) {
return (String name) -> resolver.find(name).orElse(null);
}
/**
* Creates an attribute resolver based on registered unknown patterns and resolved attribute
* values.
*
* This provides attribute lookups and unknown matching functions to the interpreter.
*/
public CelAttributeResolver createAttributeResolver() {
return DefaultAttributeResolver.create(unresolvedAttributes, resolvedAttributes);
}
/** Accessor for the underlying variable resolver. */
public GlobalResolver variableResolver() {
return variableResolver;
}
/**
* Creates a new unknown context that is a copy of the current context with the provided
* additional attribute values.
*
*
any unknown CelAttributePatterns are removed if they are satisfied by the newly resolved
* attributes.
*/
public UnknownContext withResolvedAttributes(Map resolvedAttributes) {
return new UnknownContext(
this.variableResolver,
unresolvedAttributes.stream()
.filter((pattern) -> !patternMaskedByResolvedAttribute(resolvedAttributes, pattern))
.collect(toImmutableList()),
ImmutableMap.builder()
.putAll(this.resolvedAttributes)
.putAll(resolvedAttributes)
.buildOrThrow());
}
private boolean patternMaskedByResolvedAttribute(
Map resolved, CelAttributePattern pattern) {
return resolved.keySet().stream().anyMatch(pattern::isPartialMatch);
}
/**
* Default implementation of an attribute resolver.
*
* Checks against a map of resolved attributes then a list of unknown patterns.
*/
private static class DefaultAttributeResolver implements CelAttributeResolver {
private final ImmutableList unresolvedAttributes;
private final ImmutableMap resolvedAttributes;
private DefaultAttributeResolver(
ImmutableList unresolvedAttributes,
ImmutableMap resolvedAttributes) {
this.unresolvedAttributes = unresolvedAttributes;
this.resolvedAttributes = resolvedAttributes;
}
private static DefaultAttributeResolver create(
ImmutableList attributes,
ImmutableMap resolvedAttributes) {
return new DefaultAttributeResolver(attributes, resolvedAttributes);
}
@Override
public Optional