diff --git a/spring-graphql/src/main/java/org/springframework/graphql/data/ArgumentValue.java b/spring-graphql/src/main/java/org/springframework/graphql/data/ArgumentValue.java index b25f89c4..810e79a8 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/data/ArgumentValue.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/data/ArgumentValue.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,10 @@ package org.springframework.graphql.data; import java.util.Optional; +import java.util.function.Consumer; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; /** @@ -69,6 +71,15 @@ public final class ArgumentValue { return (this.value != null); } + /** + * Return {@code true} if the input value was present in the input but the value was {@code null}, + * and {@code false} otherwise. + * @since 1.4.0 + */ + public boolean isEmpty() { + return !this.omitted && this.value == null; + } + /** * Return {@code true} if the input value was omitted altogether from the * input, and {@code false} if it was provided, but possibly set to the @@ -93,6 +104,17 @@ public final class ArgumentValue { return Optional.ofNullable(this.value); } + /** + * If a value is present, performs the given action with the value, otherwise does nothing. + * @param action the action to be performed, if a value is present + */ + public void ifPresent(Consumer action) { + Assert.notNull(action, "Action is required"); + if (this.value != null) { + action.accept(this.value); + } + } + @Override public boolean equals(Object other) { // This covers OMITTED constant diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/ArgumentValueTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/ArgumentValueTests.java new file mode 100644 index 00000000..9cba03ec --- /dev/null +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/ArgumentValueTests.java @@ -0,0 +1,84 @@ +/* + * Copyright 2020-2025 the original author or authors. + * + * 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 org.springframework.graphql.data; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link ArgumentValue}. + * @author Brian Clozel + */ +class ArgumentValueTests { + + @Test + void existingValueShouldBePresent() { + ArgumentValue message = ArgumentValue.ofNullable("hello"); + assertThat(message.isOmitted()).isFalse(); + assertThat(message.isPresent()).isTrue(); + assertThat(message.isEmpty()).isFalse(); + } + + @Test + void nullValueShouldBePresent() { + ArgumentValue message = ArgumentValue.ofNullable(null); + assertThat(message.isOmitted()).isFalse(); + assertThat(message.isPresent()).isFalse(); + assertThat(message.isEmpty()).isTrue(); + } + + @Test + void noValueShouldBeOmitted() { + ArgumentValue message = ArgumentValue.omitted(); + assertThat(message.isOmitted()).isTrue(); + assertThat(message.isPresent()).isFalse(); + assertThat(message.isEmpty()).isFalse(); + } + + @Test + void asOptionalShouldMapOmitted() { + assertThat(ArgumentValue.omitted().asOptional()).isEmpty(); + assertThat(ArgumentValue.ofNullable(null).asOptional()).isEmpty(); + assertThat(ArgumentValue.ofNullable("hello").asOptional()).isPresent(); + } + + @Test + void ifPresentShouldExecuteWhenValue() { + AtomicBoolean called = new AtomicBoolean(); + ArgumentValue.ofNullable("hello").ifPresent(value -> called.set(true)); + assertThat(called.get()).isTrue(); + } + + @Test + void ifPresentShouldSkipWhenNull() { + AtomicBoolean called = new AtomicBoolean(); + ArgumentValue.ofNullable(null).ifPresent(value -> called.set(true)); + assertThat(called.get()).isFalse(); + } + + @Test + + void ifPresentShouldSkipWhenOmitted() { + AtomicBoolean called = new AtomicBoolean(); + ArgumentValue.omitted().ifPresent(value -> called.set(true)); + assertThat(called.get()).isFalse(); + } + +}