From 61e5d8cd7697f1b0087bacbbfc725695ed7d14bf Mon Sep 17 00:00:00 2001
From: Eugene Kovko <37694937+eukovko@users.noreply.github.com>
Date: Thu, 4 Jan 2024 18:50:50 +0100
Subject: [PATCH] Bael 7436 (#15550)
* BAEL-7436: Initial Unit Tests
* BAEL-7436: Added an Example with Service
* BAEL-7436: Cleanup and test fixes
* BAEL-7436: Test rename
* BAEL-7436: Cleanup
* BAEL-7436: Fix pom
* BAEL-7436: Test rename
---
.../design-patterns-behavioral-2/pom.xml | 16 +++
.../com/baeldung/nullconversion/Address.java | 26 ++++
.../com/baeldung/nullconversion/Delivery.java | 35 +++++
.../nullconversion/DeliveryService.java | 6 +
.../com/baeldung/nullconversion/Person.java | 26 ++++
.../com/baeldung/nullconversion/ZipCode.java | 27 ++++
.../NullConversionUnitTest.java | 130 ++++++++++++++++++
.../NullReturningPersonChainProvider.java | 26 ++++
.../nullconversion/ObjectsProvider.java | 18 +++
.../ObjectsSupplierProvider.java | 20 +++
.../OnePersonDeliveryServiceUnitTest.java | 39 ++++++
.../nullconversion/PersonMutatorUtil.java | 12 ++
.../nullconversion/PersonProvider.java | 34 +++++
.../MockOnePersonDeliveryServiceBase.java | 50 +++++++
.../OnePersonExplicitDeliveryService.java | 24 ++++
...OnePersonGuavaOptionalDeliveryService.java | 26 ++++
.../OnePersonOptionalDeliveryService.java | 26 ++++
17 files changed, 541 insertions(+)
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/Address.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/Delivery.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/DeliveryService.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/Person.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/ZipCode.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/NullConversionUnitTest.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/NullReturningPersonChainProvider.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/ObjectsProvider.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/ObjectsSupplierProvider.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/OnePersonDeliveryServiceUnitTest.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/PersonMutatorUtil.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/PersonProvider.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/MockOnePersonDeliveryServiceBase.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/OnePersonExplicitDeliveryService.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/OnePersonGuavaOptionalDeliveryService.java
create mode 100644 patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/OnePersonOptionalDeliveryService.java
diff --git a/patterns-modules/design-patterns-behavioral-2/pom.xml b/patterns-modules/design-patterns-behavioral-2/pom.xml
index e484e118eb..c62e5ce205 100644
--- a/patterns-modules/design-patterns-behavioral-2/pom.xml
+++ b/patterns-modules/design-patterns-behavioral-2/pom.xml
@@ -14,4 +14,20 @@
1.0.0-SNAPSHOT
+
+
+ org.apache.commons
+ commons-lang3
+ ${apache.commons.version}
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+
+
+ 3.14.0
+
\ No newline at end of file
diff --git a/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/Address.java b/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/Address.java
new file mode 100644
index 0000000000..738be932bc
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/Address.java
@@ -0,0 +1,26 @@
+package com.baeldung.nullconversion;
+
+public class Address implements Cloneable {
+
+ private ZipCode zipCode;
+
+ public ZipCode getZipCode() {
+ return zipCode;
+ }
+
+ public void setZipCode(ZipCode zipCode) {
+ this.zipCode = zipCode;
+ }
+
+ @Override
+ protected Address clone() {
+ Address address;
+ try {
+ address = ((Address) super.clone());
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+ zipCode = zipCode.clone();
+ return address;
+ }
+}
diff --git a/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/Delivery.java b/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/Delivery.java
new file mode 100644
index 0000000000..3c584d9566
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/Delivery.java
@@ -0,0 +1,35 @@
+package com.baeldung.nullconversion;
+
+import java.util.Objects;
+
+public class Delivery {
+
+ private String message;
+
+ public Delivery(String message) {
+ this.message = message;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Delivery delivery = (Delivery) o;
+
+ return Objects.equals(message, delivery.message);
+ }
+
+ @Override
+ public int hashCode() {
+ return message != null ? message.hashCode() : 0;
+ }
+
+ public static Delivery freeDelivery() {
+ return new Delivery("Free delivery");
+ }
+}
diff --git a/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/DeliveryService.java b/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/DeliveryService.java
new file mode 100644
index 0000000000..1d3b473cdc
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/DeliveryService.java
@@ -0,0 +1,6 @@
+package com.baeldung.nullconversion;
+
+public interface DeliveryService {
+
+ Delivery calculateDeliveryForPerson(Long id);
+}
diff --git a/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/Person.java b/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/Person.java
new file mode 100644
index 0000000000..842d04575c
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/Person.java
@@ -0,0 +1,26 @@
+package com.baeldung.nullconversion;
+
+public class Person implements Cloneable {
+
+ private Address address;
+
+ public Address getAddress() {
+ return address;
+ }
+
+ public void setAddress(Address address) {
+ this.address = address;
+ }
+
+ @Override
+ protected Person clone() {
+ Person person;
+ try {
+ person = (Person) super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+ address = address.clone();
+ return person;
+ }
+}
diff --git a/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/ZipCode.java b/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/ZipCode.java
new file mode 100644
index 0000000000..0a4a1b2ed5
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/main/java/com/baeldung/nullconversion/ZipCode.java
@@ -0,0 +1,27 @@
+package com.baeldung.nullconversion;
+
+public class ZipCode implements Cloneable {
+
+ private String code;
+
+ public ZipCode(String code) {
+ this.code = code;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ @Override
+ protected ZipCode clone() {
+ try {
+ return (ZipCode) super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+}
diff --git a/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/NullConversionUnitTest.java b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/NullConversionUnitTest.java
new file mode 100644
index 0000000000..abe10f226c
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/NullConversionUnitTest.java
@@ -0,0 +1,130 @@
+package com.baeldung.nullconversion;
+
+import static java.util.Objects.requireNonNullElse;
+import static java.util.Objects.requireNonNullElseGet;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+
+import com.google.common.base.MoreObjects;
+import java.util.Optional;
+import java.util.function.Supplier;
+import org.apache.commons.lang3.ObjectUtils;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ArgumentsSource;
+
+class NullConversionUnitTest {
+
+ @ParameterizedTest
+ @ArgumentsSource(ObjectsProvider.class)
+ void givenIfWhenNotNullThenReturnsDefault(String givenValue, String defaultValue) {
+ String actual = defaultValue;
+ if (givenValue != null) {
+ actual = givenValue;
+ }
+ assertDefaultConversion(givenValue, defaultValue, actual);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(ObjectsSupplierProvider.class)
+ void givenIfWhenNotNullThenReturnsDefault(String givenValue, String expected,
+ Supplier expensiveSupplier) {
+ String actual;
+ if (givenValue != null) {
+ actual = givenValue;
+ } else {
+ actual = expensiveSupplier.get();
+ }
+ assertDefaultConversion(givenValue, expected, actual);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(ObjectsProvider.class)
+ void givenTernaryWhenNotNullThenReturnsDefault(String givenValue, String defaultValue) {
+ String actual = givenValue != null ? givenValue : defaultValue;
+ assertDefaultConversion(givenValue, defaultValue, actual);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(ObjectsSupplierProvider.class)
+ void givenLazyTernaryWhenNotNullThenReturnsDefault(String givenValue, String expected,
+ Supplier expensiveSupplier) {
+ String actual = givenValue != null ? givenValue : expensiveSupplier.get();
+ assertDefaultConversion(givenValue, expected, actual);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(ObjectsProvider.class)
+ void givenObjectsWhenNotNullThenReturnsDefault(String givenValue, String defaultValue) {
+ String actual = requireNonNullElse(givenValue, defaultValue);
+ assertDefaultConversion(givenValue, defaultValue, actual);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(ObjectsSupplierProvider.class)
+ void givenLazyObjectsWhenNotNullThenReturnsDefault(String givenValue, String expected,
+ Supplier expensiveSupplier) {
+ String actual = requireNonNullElseGet(givenValue, expensiveSupplier);
+ assertDefaultConversion(givenValue, expected, actual);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(ObjectsProvider.class)
+ void givenOptionalWhenNotNullThenReturnsDefault(String givenValue, String defaultValue) {
+ String actual = Optional.ofNullable(givenValue).orElse(defaultValue);
+ assertDefaultConversion(givenValue, defaultValue, actual);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(ObjectsSupplierProvider.class)
+ void givenLazyOptionalWhenNotNullThenReturnsDefault(String givenValue, String expected,
+ Supplier expensiveSupplier) {
+ String actual = Optional.ofNullable(givenValue).orElseGet(expensiveSupplier);
+ assertDefaultConversion(givenValue, expected, actual);
+ }
+
+
+ @ParameterizedTest
+ @ArgumentsSource(ObjectsProvider.class)
+ void givenGuavaWhenNotNullThenReturnsDefault(String givenValue, String defaultValue) {
+ String actual = MoreObjects.firstNonNull(givenValue, defaultValue);
+ assertDefaultConversion(givenValue, defaultValue, actual);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(ObjectsProvider.class)
+ void givenGuavaOptionalWhenNotNullThenReturnsDefault(String givenValue, String defaultValue) {
+ String actual = com.google.common.base.Optional.fromNullable(givenValue).or(defaultValue);
+ assertDefaultConversion(givenValue, defaultValue, actual);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(ObjectsProvider.class)
+ void givenApacheWhenNotNullThenReturnsDefault(String givenValue, String defaultValue) {
+ String actual = ObjectUtils.firstNonNull(givenValue, defaultValue);
+ assertDefaultConversion(givenValue, defaultValue, actual);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(ObjectsSupplierProvider.class)
+ void givenLazyApacheWhenNotNullThenReturnsDefault(String givenValue, String expected,
+ Supplier expensiveSupplier) {
+ String actual = ObjectUtils.getFirstNonNull(() -> givenValue, expensiveSupplier);
+ assertDefaultConversion(givenValue, expected, actual);
+ }
+
+ @Test
+ void givenAllNullsWithObjectsWhenNotNullThenThrowException() {
+ assertThatExceptionOfType(NullPointerException.class)
+ .isThrownBy(() -> requireNonNullElse(null, null));
+ }
+
+ private static void assertDefaultConversion(String given, String expected, String actual) {
+ if (given == null) {
+ assertThat(actual).isEqualTo(expected);
+ } else {
+ assertThat(actual).isEqualTo(given);
+ }
+ }
+
+}
diff --git a/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/NullReturningPersonChainProvider.java b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/NullReturningPersonChainProvider.java
new file mode 100644
index 0000000000..98232c2387
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/NullReturningPersonChainProvider.java
@@ -0,0 +1,26 @@
+package com.baeldung.nullconversion;
+
+import java.util.stream.Stream;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+
+public class NullReturningPersonChainProvider implements ArgumentsProvider {
+
+ @Override
+ public Stream extends Arguments> provideArguments(ExtensionContext context) {
+ Person person = new Person();
+ Address address = new Address();
+ ZipCode zipCode = new ZipCode("98-323");
+ address.setZipCode(zipCode);
+ person.setAddress(address);
+
+ return Stream.of(
+ Arguments.of(PersonMutatorUtil.cloneAndMutate(person, p -> p.getAddress().getZipCode().setCode(""))),
+ Arguments.of(PersonMutatorUtil.cloneAndMutate(person, p -> p.getAddress().setZipCode(null))),
+ Arguments.of(PersonMutatorUtil.cloneAndMutate(person, p -> p.setAddress(null)))
+ );
+
+ }
+
+}
diff --git a/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/ObjectsProvider.java b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/ObjectsProvider.java
new file mode 100644
index 0000000000..213947a9ce
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/ObjectsProvider.java
@@ -0,0 +1,18 @@
+package com.baeldung.nullconversion;
+
+import java.util.stream.Stream;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+
+public class ObjectsProvider implements ArgumentsProvider {
+
+ @Override
+ public Stream extends Arguments> provideArguments(ExtensionContext context) {
+ return Stream.of(
+ Arguments.of(null, "default"),
+ Arguments.of("not null", "default")
+ );
+
+ }
+}
diff --git a/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/ObjectsSupplierProvider.java b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/ObjectsSupplierProvider.java
new file mode 100644
index 0000000000..2f7688b562
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/ObjectsSupplierProvider.java
@@ -0,0 +1,20 @@
+package com.baeldung.nullconversion;
+
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+
+public class ObjectsSupplierProvider implements ArgumentsProvider {
+
+ @Override
+ public Stream extends Arguments> provideArguments(ExtensionContext context) {
+ Supplier supplier = () -> "default";
+ return Stream.of(
+ Arguments.of(null, "default", supplier),
+ Arguments.of("not null", "default", supplier)
+ );
+
+ }
+}
diff --git a/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/OnePersonDeliveryServiceUnitTest.java b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/OnePersonDeliveryServiceUnitTest.java
new file mode 100644
index 0000000000..01cd658bd1
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/OnePersonDeliveryServiceUnitTest.java
@@ -0,0 +1,39 @@
+package com.baeldung.nullconversion;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+
+import com.baeldung.nullconversion.service.OnePersonExplicitDeliveryService;
+import com.baeldung.nullconversion.service.OnePersonGuavaOptionalDeliveryService;
+import com.baeldung.nullconversion.service.OnePersonOptionalDeliveryService;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ArgumentsSource;
+
+class OnePersonDeliveryServiceUnitTest {
+
+ @ParameterizedTest
+ @ArgumentsSource(PersonProvider.class)
+ void givenMockDeliverServiceWhenNullValuesThenExplicitServiceHandleThem(Person person, Delivery expected) {
+ DeliveryService deliveryService = new OnePersonExplicitDeliveryService(person);
+ Delivery actual = deliveryService.calculateDeliveryForPerson(1L);
+ assertThat(actual).isEqualTo(expected);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(PersonProvider.class)
+ void givenMockDeliverServiceWhenNullValuesThenOptionalServiceHandleThem(Person person, Delivery expected) {
+ DeliveryService deliveryService = new OnePersonOptionalDeliveryService(person);
+ Delivery actual = deliveryService.calculateDeliveryForPerson(1L);
+ assertThat(actual).isEqualTo(expected);
+ }
+
+ @ParameterizedTest
+ @ArgumentsSource(NullReturningPersonChainProvider.class)
+ void givenMockDeliverServiceWhenNullValuesThenGuavaOptionalServiceThrowsException(Person person) {
+ DeliveryService deliveryService = new OnePersonGuavaOptionalDeliveryService(person);
+ assertThatExceptionOfType(NullPointerException.class)
+ .isThrownBy(() -> deliveryService.calculateDeliveryForPerson(1L));
+
+ }
+}
\ No newline at end of file
diff --git a/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/PersonMutatorUtil.java b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/PersonMutatorUtil.java
new file mode 100644
index 0000000000..3165ecad4e
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/PersonMutatorUtil.java
@@ -0,0 +1,12 @@
+package com.baeldung.nullconversion;
+
+import java.util.function.Consumer;
+
+public class PersonMutatorUtil {
+
+ public static Person cloneAndMutate(Person person, Consumer mutator) {
+ Person clone = person.clone();
+ mutator.accept(clone);
+ return clone;
+ }
+}
diff --git a/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/PersonProvider.java b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/PersonProvider.java
new file mode 100644
index 0000000000..d31d9d8ec4
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/PersonProvider.java
@@ -0,0 +1,34 @@
+package com.baeldung.nullconversion;
+
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+
+public class PersonProvider implements ArgumentsProvider {
+
+ @Override
+ public Stream extends Arguments> provideArguments(ExtensionContext context) {
+ Person person = new Person();
+ Address address = new Address();
+ ZipCode zipCode = new ZipCode("98-323");
+ address.setZipCode(zipCode);
+ person.setAddress(address);
+
+ return Stream.of(
+ Arguments.of(person, Delivery.freeDelivery()),
+ Arguments.of(cloneAndMutate(person, p -> p.getAddress().getZipCode().setCode("")), null),
+ Arguments.of(cloneAndMutate(person, p -> p.getAddress().setZipCode(null)), null),
+ Arguments.of(cloneAndMutate(person, p -> p.setAddress(null)), null),
+ Arguments.of(null, null)
+ );
+
+ }
+
+ private static Person cloneAndMutate(Person person, Consumer mutator) {
+ Person clone = person.clone();
+ mutator.accept(clone);
+ return clone;
+ }
+}
diff --git a/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/MockOnePersonDeliveryServiceBase.java b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/MockOnePersonDeliveryServiceBase.java
new file mode 100644
index 0000000000..973f8bce97
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/MockOnePersonDeliveryServiceBase.java
@@ -0,0 +1,50 @@
+package com.baeldung.nullconversion.service;
+
+import com.baeldung.nullconversion.Address;
+import com.baeldung.nullconversion.Delivery;
+import com.baeldung.nullconversion.DeliveryService;
+import com.baeldung.nullconversion.Person;
+import com.baeldung.nullconversion.ZipCode;
+import java.util.Optional;
+
+public abstract class MockOnePersonDeliveryServiceBase implements DeliveryService {
+
+ private final Person person;
+
+ public MockOnePersonDeliveryServiceBase(Person person) {
+ this.person = person;
+ }
+
+ @Override
+ public Delivery calculateDeliveryForPerson(Long id) {
+ Person person = getPersonById(id);
+ if (person != null && person.getAddress() != null && person.getAddress().getZipCode() != null) {
+ ZipCode zipCode = person.getAddress().getZipCode();
+ String code = zipCode.getCode();
+ return calculateDeliveryForZipCode(code);
+ }
+ return null;
+ }
+
+ public Delivery calculateDeliveryForPersonWithOptional(Long id) {
+ return Optional.ofNullable(getPersonById(id))
+ .map(Person::getAddress)
+ .map(Address::getZipCode)
+ .map(ZipCode::getCode)
+ .map(this::calculateDeliveryForZipCode)
+ .orElse(null);
+ }
+
+ protected Person getPersonById(Long id) {
+ return person;
+ }
+
+ protected Delivery calculateDeliveryForZipCode(String zipCode) {
+ if (zipCode == null || zipCode.isEmpty()) {
+ return null;
+ } else {
+ return Delivery.freeDelivery();
+ }
+ }
+
+}
diff --git a/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/OnePersonExplicitDeliveryService.java b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/OnePersonExplicitDeliveryService.java
new file mode 100644
index 0000000000..652d0a002b
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/OnePersonExplicitDeliveryService.java
@@ -0,0 +1,24 @@
+package com.baeldung.nullconversion.service;
+
+import com.baeldung.nullconversion.Delivery;
+import com.baeldung.nullconversion.Person;
+import com.baeldung.nullconversion.ZipCode;
+
+public class OnePersonExplicitDeliveryService extends MockOnePersonDeliveryServiceBase {
+
+
+ public OnePersonExplicitDeliveryService(Person person) {
+ super(person);
+ }
+
+ @Override
+ public Delivery calculateDeliveryForPerson(Long id) {
+ Person person = getPersonById(id);
+ if (person != null && person.getAddress() != null && person.getAddress().getZipCode() != null) {
+ ZipCode zipCode = person.getAddress().getZipCode();
+ String code = zipCode.getCode();
+ return calculateDeliveryForZipCode(code);
+ }
+ return null;
+ }
+}
diff --git a/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/OnePersonGuavaOptionalDeliveryService.java b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/OnePersonGuavaOptionalDeliveryService.java
new file mode 100644
index 0000000000..29d42789a0
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/OnePersonGuavaOptionalDeliveryService.java
@@ -0,0 +1,26 @@
+package com.baeldung.nullconversion.service;
+
+import com.baeldung.nullconversion.Address;
+import com.baeldung.nullconversion.Delivery;
+import com.baeldung.nullconversion.Person;
+import com.baeldung.nullconversion.ZipCode;
+import com.google.common.base.Optional;
+
+public class OnePersonGuavaOptionalDeliveryService extends MockOnePersonDeliveryServiceBase {
+
+
+ public OnePersonGuavaOptionalDeliveryService(Person person) {
+ super(person);
+ }
+
+ @Override
+ public Delivery calculateDeliveryForPerson(Long id) {
+ return Optional.fromNullable(getPersonById(id))
+ .transform(Person::getAddress)
+ .transform(Address::getZipCode)
+ .transform(ZipCode::getCode)
+ .transform(this::calculateDeliveryForZipCode)
+ .orNull();
+ }
+
+}
diff --git a/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/OnePersonOptionalDeliveryService.java b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/OnePersonOptionalDeliveryService.java
new file mode 100644
index 0000000000..586f0009ea
--- /dev/null
+++ b/patterns-modules/design-patterns-behavioral-2/src/test/java/com/baeldung/nullconversion/service/OnePersonOptionalDeliveryService.java
@@ -0,0 +1,26 @@
+package com.baeldung.nullconversion.service;
+
+import com.baeldung.nullconversion.Address;
+import com.baeldung.nullconversion.Delivery;
+import com.baeldung.nullconversion.Person;
+import com.baeldung.nullconversion.ZipCode;
+import java.util.Optional;
+
+public class OnePersonOptionalDeliveryService extends MockOnePersonDeliveryServiceBase {
+
+
+ public OnePersonOptionalDeliveryService(Person person) {
+ super(person);
+ }
+
+ @Override
+ public Delivery calculateDeliveryForPerson(Long id) {
+ return Optional.ofNullable(getPersonById(id))
+ .map(Person::getAddress)
+ .map(Address::getZipCode)
+ .map(ZipCode::getCode)
+ .map(this::calculateDeliveryForZipCode)
+ .orElse(null);
+ }
+
+}