[SR] Map enum with mapstruct (#16163)

* Added enums for week day, its mapper and test.

* Added enums, mapping and tests for case transformation.

* Changed test names to follow BDD style.

* Renamed test class.

* Removed enum, mapper and test for weekdays.
Added same for traffic signal.

* Moved the source code and tests under its own package.

* Added link to article.

* Fixed readme

* Fixed readme

---------

Co-authored-by: sraverkar.encora <sraverkar.encora@centricsoftware.com>
This commit is contained in:
Sachin Raverkar 2024-04-03 06:44:20 +05:30 committed by GitHub
parent 8ac5afda83
commit 6719beae86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 631 additions and 0 deletions

View File

@ -0,0 +1,208 @@
package com.baeldung.mapstruct.enums.mapper;
import com.baeldung.mapstruct.enums.model.*;
import org.mapstruct.*;
import org.mapstruct.factory.Mappers;
/**
* The Traffic signal mapper.
*/
@Mapper
public interface TrafficSignalMapper {
/**
* The constant INSTANCE.
*/
TrafficSignalMapper INSTANCE = Mappers.getMapper(TrafficSignalMapper.class);
/**
* Convert traffic signal to integer.
*
* @param source the source
* @return the integer
*/
default Integer convertTrafficSignalToInteger(TrafficSignal source) {
Integer result = null;
switch (source) {
case Off:
result = 0;
break;
case Stop:
result = 1;
break;
case Go:
result = 2;
break;
}
return result;
}
/**
* Maps road sign to traffic signal.
*
* @param source the source
* @return the traffic signal
*/
@ValueMapping(target = "Off", source = "Off")
@ValueMapping(target = "Go", source = "Move")
@ValueMapping(target = "Stop", source = "Halt")
TrafficSignal toTrafficSignal(RoadSign source);
/**
* Maps string to traffic signal.
*
* @param source the source
* @return the traffic signal
*/
@ValueMapping(target = "Off", source = "Off")
@ValueMapping(target = "Go", source = "Move")
@ValueMapping(target = "Stop", source = "Halt")
TrafficSignal stringToTrafficSignal(String source);
/**
* Maps a traffic signal to string.
*
* @param source the source
* @return the traffic signal
*/
@ValueMapping(target = "Off", source = "Off")
@ValueMapping(target = "Go", source = "Go")
@ValueMapping(target = "Stop", source = "Stop")
String trafficSignalToString(TrafficSignal source);
/**
* Maps a traffic signal to number.
*
* @param source the source
* @return the traffic signal number
*/
@Mapping(target = "number", source = ".")
TrafficSignalNumber trafficSignalToTrafficSignalNumber(TrafficSignal source);
/**
* Maps traffic signal to simple traffic signal.
*
* @param source the source
* @return the simple traffic signal
*/
@ValueMapping(target = "Off", source = "Off")
@ValueMapping(target = "On", source = "Go")
@ValueMapping(target = "Off", source = "Stop")
SimpleTrafficSignal toSimpleTrafficSignal(TrafficSignal source);
/**
* Maps traffic signal to simple traffic signal.
*
* @param source the source
* @return the simple traffic signal
*/
@ValueMapping(target = "On", source = "Go")
@ValueMapping(target = "Off", source = MappingConstants.ANY_REMAINING)
SimpleTrafficSignal toSimpleTrafficSignalWithRemaining(TrafficSignal source);
/**
* Maps traffic signal to simple traffic signal.
*
* @param source the source
* @return the simple traffic signal
*/
@ValueMapping(target = "On", source = "Go")
@ValueMapping(target = "Off", source = MappingConstants.ANY_UNMAPPED)
SimpleTrafficSignal toSimpleTrafficSignalWithUnmapped(TrafficSignal source);
/**
* Maps traffic signal with null handling.
*
* @param source the source
* @return the work day
*/
@ValueMapping(target = "Off", source = MappingConstants.NULL)
@ValueMapping(target = "On", source = "Go")
@ValueMapping(target = MappingConstants.NULL, source = MappingConstants.ANY_UNMAPPED)
SimpleTrafficSignal toSimpleTrafficSignalWithNullHandling(TrafficSignal source);
/**
* Maps simple traffic signal to traffic signal with exception handling.
*
* @param source the source
* @return the work day
* @throws IllegalArgumentException if {@code source} is {@code Sat} or {@code Sun}.
*/
@ValueMapping(target = "On", source = "Go")
@ValueMapping(target = MappingConstants.THROW_EXCEPTION, source = MappingConstants.NULL)
@ValueMapping(target = MappingConstants.THROW_EXCEPTION, source = MappingConstants.ANY_UNMAPPED)
SimpleTrafficSignal toSimpleTrafficSignalWithExceptionHandling(TrafficSignal source);
/**
* Apply suffix.
*
* @param source the source
* @return traffic signal suffixed
*/
@EnumMapping(nameTransformationStrategy = MappingConstants.SUFFIX_TRANSFORMATION, configuration = "_Value")
TrafficSignalSuffixed applySuffix(TrafficSignal source);
/**
* Apply prefix.
*
* @param source the source
* @return the traffic signal prefixed
*/
@EnumMapping(nameTransformationStrategy = MappingConstants.PREFIX_TRANSFORMATION, configuration = "Value_")
TrafficSignalPrefixed applyPrefix(TrafficSignal source);
/**
* Strip suffix.
*
* @param source the source
* @return the traffic signal
*/
@EnumMapping(nameTransformationStrategy = MappingConstants.STRIP_SUFFIX_TRANSFORMATION, configuration = "_Value")
TrafficSignal stripSuffix(TrafficSignalSuffixed source);
/**
* Strip prefix.
*
* @param source the source
* @return the traffic signal
*/
@EnumMapping(nameTransformationStrategy = MappingConstants.STRIP_PREFIX_TRANSFORMATION, configuration = "Value_")
TrafficSignal stripPrefix(TrafficSignalPrefixed source);
/**
* Apply lowercase to traffic signal.
*
* @param source the source
* @return the traffic signal lowercase
*/
@EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "lower")
TrafficSignalLowercase applyLowercase(TrafficSignal source);
/**
* Apply uppercase to traffic signal.
*
* @param source the source
* @return the traffic signal uppercase
*/
@EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "upper")
TrafficSignalUppercase applyUppercase(TrafficSignal source);
/**
* Underscore to string in capital case.
*
* @param source the source
* @return the string
*/
@EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "capital")
String underscoreToCapital(TrafficSignalUnderscore source);
/**
* Lowercase to capital traffic signal.
*
* @param source the source
* @return traffic signal
*/
@EnumMapping(nameTransformationStrategy = MappingConstants.CASE_TRANSFORMATION, configuration = "capital")
TrafficSignal lowercaseToCapital(TrafficSignalLowercase source);
}

View File

@ -0,0 +1,19 @@
package com.baeldung.mapstruct.enums.model;
/**
* The enum road signal.
*/
public enum RoadSign {
/**
* Off signal.
*/
Off,
/**
* Stop signal.
*/
Halt,
/**
* Go signal.
*/
Move
}

View File

@ -0,0 +1,15 @@
package com.baeldung.mapstruct.enums.model;
/**
* The enum two-state Traffic Signal.
*/
public enum SimpleTrafficSignal {
/**
* Off signal.
*/
Off,
/**
* Stop signal.
*/
On
}

View File

@ -0,0 +1,19 @@
package com.baeldung.mapstruct.enums.model;
/**
* The enum Traffic Signal.
*/
public enum TrafficSignal {
/**
* Off signal.
*/
Off,
/**
* Stop signal.
*/
Stop,
/**
* Go signal.
*/
Go
}

View File

@ -0,0 +1,19 @@
package com.baeldung.mapstruct.enums.model;
/**
* The enum Traffic Signal with lowercase.
*/
public enum TrafficSignalLowercase {
/**
* Off signal.
*/
off,
/**
* Stop signal.
*/
stop,
/**
* Go signal.
*/
go
}

View File

@ -0,0 +1,26 @@
package com.baeldung.mapstruct.enums.model;
/**
* The traffic signal number.
*/
public class TrafficSignalNumber {
private Integer number;
/**
* Gets number.
*
* @return the number
*/
public Integer getNumber() {
return number;
}
/**
* Sets number.
*
* @param number the number
*/
public void setNumber(Integer number) {
this.number = number;
}
}

View File

@ -0,0 +1,19 @@
package com.baeldung.mapstruct.enums.model;
/**
* The enum Traffic Signal with prefix.
*/
public enum TrafficSignalPrefixed {
/**
* Off signal.
*/
Value_Off,
/**
* Stop signal.
*/
Value_Stop,
/**
* Go signal.
*/
Value_Go
}

View File

@ -0,0 +1,19 @@
package com.baeldung.mapstruct.enums.model;
/**
* The enum Traffic Signal with suffix.
*/
public enum TrafficSignalSuffixed {
/**
* Off signal.
*/
Off_Value,
/**
* Stop signal.
*/
Stop_Value,
/**
* Go signal.
*/
Go_Value
}

View File

@ -0,0 +1,19 @@
package com.baeldung.mapstruct.enums.model;
/**
* The enum Traffic Signal with uppercase.
*/
public enum TrafficSignalUnderscore {
/**
* Off signal.
*/
OFF_VALUE,
/**
* Stop signal.
*/
STOP_VALUE,
/**
* Go signal.
*/
GO_VALUE
}

View File

@ -0,0 +1,19 @@
package com.baeldung.mapstruct.enums.model;
/**
* The enum Traffic Signal with uppercase.
*/
public enum TrafficSignalUppercase {
/**
* Off signal.
*/
OFF,
/**
* Stop signal.
*/
STOP,
/**
* Go signal.
*/
GO
}

View File

@ -0,0 +1,249 @@
package com.baeldung.mapstruct.enums;
import com.baeldung.mapstruct.enums.mapper.TrafficSignalMapper;
import com.baeldung.mapstruct.enums.model.*;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
/**
* The traffic signal mapper test.
*/
class TrafficSignalMapperUnitTest {
/**
* To traffic signal.
*/
@Test
void whenRoadSignIsMapped_thenGetTrafficSignal() {
RoadSign source = RoadSign.Move;
TrafficSignal target = TrafficSignalMapper.INSTANCE.toTrafficSignal(source);
assertEquals(TrafficSignal.Go, target);
}
/**
* String to traffic signal.
*/
@Test
void whenStringIsMapped_thenGetTrafficSignal() {
String source = RoadSign.Move.name();
TrafficSignal target = TrafficSignalMapper.INSTANCE.stringToTrafficSignal(source);
assertEquals(TrafficSignal.Go, target);
}
/**
* String to unmapped traffic signal.
*/
@Test
void whenStringIsUnmapped_thenGetException() {
String source = "Proceed";
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
TrafficSignalMapper.INSTANCE.stringToTrafficSignal(source);
});
assertEquals("Unexpected enum constant: " + source, exception.getMessage());
}
/**
* Traffic signal to string.
*/
@Test
void whenTrafficSignalIsMapped_thenGetString() {
TrafficSignal source = TrafficSignal.Go;
String targetTrafficSignalStr = TrafficSignalMapper.INSTANCE.trafficSignalToString(source);
assertEquals("Go", targetTrafficSignalStr);
}
/**
* Traffic signal to int.
*
* @param source the traffic signal
* @param expected the expected traffic signal number
*/
@ParameterizedTest
@CsvSource({"Off,0", "Stop,1"})
void whenTrafficSignalIsMapped_thenGetInt(TrafficSignal source, int expected) {
Integer targetTrafficSignalInt = TrafficSignalMapper.INSTANCE.convertTrafficSignalToInteger(source);
TrafficSignalNumber targetTrafficSignalNumber = TrafficSignalMapper.INSTANCE.trafficSignalToTrafficSignalNumber(source);
assertEquals(expected, targetTrafficSignalInt.intValue());
assertEquals(expected, targetTrafficSignalNumber.getNumber().intValue());
}
/**
* Traffic signal to simple traffic signal.
*
* @param source the traffic signal
* @param expected the expected traffic signal
*/
@ParameterizedTest
@CsvSource({"Off,Off", "Go,On", "Stop,Off"})
void whenTrafficSignalIsMapped_thenGetSimpleTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) {
SimpleTrafficSignal target = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignal(source);
assertEquals(expected, target);
}
/**
* Traffic signal to working day.
*
* @param source the traffic signal
* @param expected the expected traffic signal
*/
@ParameterizedTest
@CsvSource({"Off,Off", "Go,On", "Stop,Off"})
void whenTrafficSignalIsMappedWithRemaining_thenGetTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) {
SimpleTrafficSignal targetTrafficSignal = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithRemaining(source);
assertEquals(expected, targetTrafficSignal);
}
/**
* Traffic signal to working day.
*
* @param source the traffic signal
* @param expected the expected traffic signal
*/
@ParameterizedTest
@CsvSource({"Off,Off", "Go,On", "Stop,Off"})
void whenTrafficSignalIsMappedWithUnmapped_thenGetTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) {
SimpleTrafficSignal target = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithUnmapped(source);
assertEquals(expected, target);
}
/**
* Traffic signal to simple traffic signal with null handling.
*
* @param source the traffic signal
* @param expected the expected traffic signal
*/
@ParameterizedTest
@CsvSource({",Off", "Go,On", "Stop,"})
void whenTrafficSignalIsMappedWithNull_thenGetTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) {
SimpleTrafficSignal targetTrafficSignal = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithNullHandling(source);
assertEquals(expected, targetTrafficSignal);
}
/**
* Traffic signal to traffic signal with exception handling.
*
* @param source the traffic signal
* @param expected the expected traffic signal
*/
@ParameterizedTest
@CsvSource({",", "Go,On", "Stop,"})
void whenTrafficSignalIsMappedWithException_thenGetTrafficSignal(TrafficSignal source, SimpleTrafficSignal expected) {
if (source == TrafficSignal.Go) {
SimpleTrafficSignal targetTrafficSignal = TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithExceptionHandling(source);
assertEquals(expected, targetTrafficSignal);
} else {
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
TrafficSignalMapper.INSTANCE.toSimpleTrafficSignalWithExceptionHandling(source);
});
assertEquals("Unexpected enum constant: " + source, exception.getMessage());
}
}
/**
* Apply suffix.
*
* @param source the traffic signal
* @param expected the expected result
*/
@ParameterizedTest
@CsvSource({"Off,Off_Value", "Go,Go_Value"})
void whenTrafficSignalIsMappedWithSuffix_thenGetTrafficSignalSuffixed(TrafficSignal source, TrafficSignalSuffixed expected) {
TrafficSignalSuffixed result = TrafficSignalMapper.INSTANCE.applySuffix(source);
assertEquals(expected, result);
}
/**
* Apply prefix.
*
* @param source the traffic signal
* @param expected the expected result
*/
@ParameterizedTest
@CsvSource({"Off,Value_Off", "Go,Value_Go"})
void whenTrafficSignalIsMappedWithPrefix_thenGetTrafficSignalPrefixed(TrafficSignal source, TrafficSignalPrefixed expected) {
TrafficSignalPrefixed result = TrafficSignalMapper.INSTANCE.applyPrefix(source);
assertEquals(expected, result);
}
/**
* Strip suffix.
*
* @param source the traffic signal
* @param expected the expected result
*/
@ParameterizedTest
@CsvSource({"Off_Value,Off", "Go_Value,Go"})
void whenTrafficSignalSuffixedMappedWithStripped_thenGetTrafficSignal(TrafficSignalSuffixed source, TrafficSignal expected) {
TrafficSignal result = TrafficSignalMapper.INSTANCE.stripSuffix(source);
assertEquals(expected, result);
}
/**
* Strip prefix.
*
* @param source the traffic signal
* @param expected the expected result
*/
@ParameterizedTest
@CsvSource({"Value_Off,Off", "Value_Stop,Stop"})
void whenTrafficSignalPrefixedMappedWithStripped_thenGetTrafficSignal(TrafficSignalPrefixed source, TrafficSignal expected) {
TrafficSignal result = TrafficSignalMapper.INSTANCE.stripPrefix(source);
assertEquals(expected, result);
}
/**
* Apply lowercase.
*
* @param source the traffic signal
* @param expected the expected result
*/
@ParameterizedTest
@CsvSource({"Off,off", "Go,go"})
void whenTrafficSignalMappedWithLower_thenGetTrafficSignalLowercase(TrafficSignal source, TrafficSignalLowercase expected) {
TrafficSignalLowercase result = TrafficSignalMapper.INSTANCE.applyLowercase(source);
assertEquals(expected, result);
}
/**
* Apply uppercase.
*
* @param source the traffic signal
* @param expected the expected result
*/
@ParameterizedTest
@CsvSource({"Off,OFF", "Go,GO"})
void whenTrafficSignalMappedWithUpper_thenGetTrafficSignalUppercase(TrafficSignal source, TrafficSignalUppercase expected) {
TrafficSignalUppercase result = TrafficSignalMapper.INSTANCE.applyUppercase(source);
assertEquals(expected, result);
}
/**
* Underscore to capital.
*
* @param source the traffic signal
* @param expected the expected result
*/
@ParameterizedTest
@CsvSource({"OFF_VALUE,Off_Value", "GO_VALUE,Go_Value"})
void whenTrafficSignalUnderscoreMappedWithCapital_thenGetStringCapital(TrafficSignalUnderscore source, String expected) {
String result = TrafficSignalMapper.INSTANCE.underscoreToCapital(source);
assertEquals(expected, result);
}
/**
* Lowercase to capital.
*
* @param source the traffic signal
* @param expected the expected result
*/
@ParameterizedTest
@CsvSource({"off,Off", "go,Go"})
void whenTrafficSignalLowercaseMappedWithCapital_thenGetTrafficSignal(TrafficSignalLowercase source, TrafficSignal expected) {
TrafficSignal result = TrafficSignalMapper.INSTANCE.lowercaseToCapital(source);
assertEquals(expected, result);
}
}