1515package dev .cel .parser ;
1616
1717import static com .google .common .base .Preconditions .checkNotNull ;
18+ import static java .util .stream .Collectors .toCollection ;
1819
1920import com .google .common .annotations .VisibleForTesting ;
21+ import com .google .common .collect .ImmutableList ;
2022import com .google .common .collect .ImmutableMap ;
2123import com .google .common .collect .ImmutableSet ;
2224import com .google .common .collect .Iterables ;
3234import java .util .ArrayList ;
3335import java .util .Arrays ;
3436import java .util .HashMap ;
37+ import java .util .HashSet ;
3538import java .util .List ;
3639import java .util .Map ;
3740import java .util .Optional ;
41+ import java .util .stream .Collectors ;
3842
3943/**
4044 * Modernized parser implementation for CEL.
@@ -54,9 +58,10 @@ public final class CelParserImpl implements CelParser, EnvVisitable {
5458 // Specific options for limits on parsing power.
5559 private final CelOptions options ;
5660
57- // Builder is mutable by design. APIs must make defensive copies in and out of this class.
58- @ SuppressWarnings ("Immutable" )
59- private final Builder parserBuilder ;
61+ private final ImmutableList <CelStandardMacro > standardMacros ;
62+
63+ @ SuppressWarnings ("Immutable" ) // Interface not marked as immutable, however it should be.
64+ private final ImmutableSet <CelParserLibrary > parserLibraries ;
6065
6166 /** Creates a new {@link Builder}. */
6267 public static CelParserBuilder newBuilder () {
@@ -75,7 +80,20 @@ public CelValidationResult parse(CelSource source) {
7580
7681 @ Override
7782 public CelParserBuilder toParserBuilder () {
78- return new Builder (parserBuilder );
83+ HashSet <String > standardMacroKeys =
84+ standardMacros .stream ()
85+ .map (s -> s .getDefinition ().getKey ())
86+ .collect (Collectors .toCollection (HashSet ::new ));
87+
88+ return new Builder ()
89+ .setOptions (options )
90+ .setStandardMacros (standardMacros )
91+ .addMacros (
92+ // Separate standard macros from the custom macros before constructing the builder
93+ macros .values ().stream ()
94+ .filter (m -> !standardMacroKeys .contains (m .getKey ()))
95+ .collect (toCollection (ArrayList ::new )))
96+ .addLibraries (parserLibraries );
7997 }
8098
8199 Optional <CelMacro > findMacro (String key ) {
@@ -175,37 +193,35 @@ public CelParserImpl build() {
175193 // Add libraries, such as extensions
176194 parserLibrarySet .forEach (celLibrary -> celLibrary .setParserOptions (this ));
177195
178- ImmutableMap .Builder <String , CelMacro > builder = ImmutableMap .builder ();
179- builder .putAll (macros );
196+ ImmutableMap .Builder <String , CelMacro > macroMapBuilder = ImmutableMap .builder ();
197+ macroMapBuilder .putAll (macros );
180198 standardMacros .stream ()
181199 .map (CelStandardMacro ::getDefinition )
182- .forEach (celMacro -> builder .put (celMacro .getKey (), celMacro ));
183- return new CelParserImpl (builder .buildOrThrow (), checkNotNull (options ), this );
200+ .forEach (celMacro -> macroMapBuilder .put (celMacro .getKey (), celMacro ));
201+
202+ return new CelParserImpl (
203+ macroMapBuilder .buildOrThrow (),
204+ options ,
205+ ImmutableList .copyOf (standardMacros ),
206+ celParserLibraries .build ());
184207 }
185208
186209 private Builder () {
187210 this .macros = new HashMap <>();
188211 this .celParserLibraries = ImmutableSet .builder ();
189212 this .standardMacros = new ArrayList <>();
190213 }
191-
192- private Builder (Builder builder ) {
193- // The following properties are either immutable or simple primitives, thus can be assigned
194- // directly.
195- this .options = builder .options ;
196- // The following needs to be deep copied as they are collection builders
197- this .macros = new HashMap <>(builder .macros );
198- this .standardMacros = new ArrayList <>(builder .standardMacros );
199- this .celParserLibraries = ImmutableSet .builder ();
200- this .celParserLibraries .addAll (builder .celParserLibraries .build ());
201- }
202214 }
203215
204216 private CelParserImpl (
205- ImmutableMap <String , CelMacro > macros , CelOptions options , Builder parserBuilder ) {
217+ ImmutableMap <String , CelMacro > macros ,
218+ CelOptions options ,
219+ ImmutableList <CelStandardMacro > standardMacros ,
220+ ImmutableSet <CelParserLibrary > parserLibraries ) {
206221 this .macros = macros ;
207- this .options = options ;
208- this .parserBuilder = new Builder (parserBuilder );
222+ this .options = checkNotNull (options );
223+ this .standardMacros = standardMacros ;
224+ this .parserLibraries = parserLibraries ;
209225 }
210226
211227 @ Override
0 commit comments