diff --git a/mapstruct-2/src/main/java/com/baeldung/context/entity/Trade.java b/mapstruct-2/src/main/java/com/baeldung/context/entity/Trade.java new file mode 100644 index 000000000000..84dba551a7b0 --- /dev/null +++ b/mapstruct-2/src/main/java/com/baeldung/context/entity/Trade.java @@ -0,0 +1,37 @@ +package com.baeldung.context.entity; + +public class Trade { + private String securityID; + private int quantity; + private double price; + + public Trade(String securityID, int quantity, double price) { + this.securityID = securityID; + this.quantity = quantity; + this.price = price; + } + + public String getSecurityID() { + return securityID; + } + + public void setSecurityID(String securityID) { + this.securityID = securityID; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } +} diff --git a/mapstruct-2/src/main/java/com/baeldung/context/entity/TradeDto.java b/mapstruct-2/src/main/java/com/baeldung/context/entity/TradeDto.java new file mode 100644 index 000000000000..a511a913aa78 --- /dev/null +++ b/mapstruct-2/src/main/java/com/baeldung/context/entity/TradeDto.java @@ -0,0 +1,44 @@ +package com.baeldung.context.entity; + +public class TradeDto { + private String securityIdentifier; + private int quantity; + private double price; + + public TradeDto() { + } + + public TradeDto(String securityIdentifier, int quantity, double price) { + this.securityIdentifier = securityIdentifier; + this.quantity = quantity; + this.price = price; + } + + public TradeDto(String SecurityIdentifier) { + this.securityIdentifier = SecurityIdentifier; + } + + public String getSecurityIdentifier() { + return securityIdentifier; + } + + public void setSecurityIdentifier(String securityIdentifier) { + this.securityIdentifier = securityIdentifier; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } +} diff --git a/mapstruct-2/src/main/java/com/baeldung/context/mapper/TradeMapperUsingObjectFactory.java b/mapstruct-2/src/main/java/com/baeldung/context/mapper/TradeMapperUsingObjectFactory.java new file mode 100644 index 000000000000..5e657ec63a8f --- /dev/null +++ b/mapstruct-2/src/main/java/com/baeldung/context/mapper/TradeMapperUsingObjectFactory.java @@ -0,0 +1,23 @@ +package com.baeldung.context.mapper; + +import org.mapstruct.Context; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.context.entity.Trade; +import com.baeldung.context.entity.TradeDto; +import com.baeldung.context.service.TradeDtoFactory; + +@Mapper(uses = TradeDtoFactory.class) +public abstract class TradeMapperUsingObjectFactory { + final Logger logger = LoggerFactory.getLogger(TradeMapperUsingObjectFactory.class); + + public static TradeMapperUsingObjectFactory getInstance() { + return Mappers.getMapper(TradeMapperUsingObjectFactory.class); + } + + protected abstract TradeDto toTradeDto(Trade trade, @Context String identifierType); +} diff --git a/mapstruct-2/src/main/java/com/baeldung/context/mapper/TradeMapperWithAfterMapping.java b/mapstruct-2/src/main/java/com/baeldung/context/mapper/TradeMapperWithAfterMapping.java new file mode 100644 index 000000000000..5325cf264c71 --- /dev/null +++ b/mapstruct-2/src/main/java/com/baeldung/context/mapper/TradeMapperWithAfterMapping.java @@ -0,0 +1,32 @@ +package com.baeldung.context.mapper; + +import org.mapstruct.AfterMapping; +import org.mapstruct.Context; +import org.mapstruct.Mapper; +import org.mapstruct.MappingTarget; +import org.mapstruct.factory.Mappers; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.context.entity.Trade; +import com.baeldung.context.entity.TradeDto; +import com.baeldung.context.service.SecurityService; + +@Mapper +public abstract class TradeMapperWithAfterMapping { + final Logger logger = LoggerFactory.getLogger(TradeMapperWithAfterMapping.class); + + public static TradeMapperWithAfterMapping getInstance() { + return Mappers.getMapper(TradeMapperWithAfterMapping.class); + } + + protected abstract TradeDto toTradeDto(Trade trade, @Context String identifierType); + + @AfterMapping + protected TradeDto convertToIdentifier(Trade trade, @MappingTarget TradeDto tradeDto, @Context String identifierType) { + logger.info("convertToIdentifier(): Converting to identifier type: {}", identifierType); + SecurityService securityService = new SecurityService(); + tradeDto.setSecurityIdentifier(securityService.getSecurityIdentifierOfType(trade.getSecurityID(), identifierType)); + return tradeDto; + } +} \ No newline at end of file diff --git a/mapstruct-2/src/main/java/com/baeldung/context/mapper/TradeMapperWithBeforeMapping.java b/mapstruct-2/src/main/java/com/baeldung/context/mapper/TradeMapperWithBeforeMapping.java new file mode 100644 index 000000000000..ba34f2001660 --- /dev/null +++ b/mapstruct-2/src/main/java/com/baeldung/context/mapper/TradeMapperWithBeforeMapping.java @@ -0,0 +1,34 @@ +package com.baeldung.context.mapper; + +import org.mapstruct.BeforeMapping; +import org.mapstruct.Context; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.context.entity.Trade; +import com.baeldung.context.entity.TradeDto; +import com.baeldung.context.service.SecurityService; + +@Mapper +public abstract class TradeMapperWithBeforeMapping { + final Logger logger = LoggerFactory.getLogger(TradeMapperWithBeforeMapping.class); + + protected SecurityService securityService; + + public static TradeMapperWithBeforeMapping getInstance() { + return Mappers.getMapper(TradeMapperWithBeforeMapping.class); + } + + @BeforeMapping + protected void initialize(@Context Integer exchangeCode) { + logger.info("initialize(): Initializing SecurityService with identifier type: {}", exchangeCode); + securityService = new SecurityService(exchangeCode); + } + + @Mapping(target="securityIdentifier", expression = "java(securityService.getSecurityIdentifierOfType(trade.getSecurityID(), identifierType))") + protected abstract TradeDto toTradeDto(Trade trade, @Context String identifierType, @Context Integer exchangeCode); + +} diff --git a/mapstruct-2/src/main/java/com/baeldung/context/service/SecurityService.java b/mapstruct-2/src/main/java/com/baeldung/context/service/SecurityService.java new file mode 100644 index 000000000000..b33cfc9deb08 --- /dev/null +++ b/mapstruct-2/src/main/java/com/baeldung/context/service/SecurityService.java @@ -0,0 +1,31 @@ +package com.baeldung.context.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SecurityService { + + private final Logger logger = LoggerFactory.getLogger(SecurityService.class); + + private Integer exchangeCode; + + public SecurityService() { + + } + + public SecurityService(Integer exchangeCode) { + logger.info("SecurityService initialized with identifier type: {}", exchangeCode); + } + + public String getSecurityIdentifierOfType(String securityID, String identifierType) { + // Simulate fetching security details from a database or external service + logger.info("Fetching {} for security ID: {}", identifierType, securityID); + + return switch (identifierType.toUpperCase()) { + case "ISIN" -> "US0378331005"; + case "CUSIP" -> "037833100"; + case "SEDOL" -> "B1Y8QX7"; + default -> null; + }; + } +} diff --git a/mapstruct-2/src/main/java/com/baeldung/context/service/TradeDtoFactory.java b/mapstruct-2/src/main/java/com/baeldung/context/service/TradeDtoFactory.java new file mode 100644 index 000000000000..3302a5db9283 --- /dev/null +++ b/mapstruct-2/src/main/java/com/baeldung/context/service/TradeDtoFactory.java @@ -0,0 +1,24 @@ +package com.baeldung.context.service; + +import org.mapstruct.Context; +import org.mapstruct.ObjectFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.context.entity.Trade; +import com.baeldung.context.entity.TradeDto; + +public class TradeDtoFactory { + private static final Logger logger = LoggerFactory.getLogger(TradeDtoFactory.class); + + @ObjectFactory + public TradeDto createTradeDto(Trade trade, @Context String identifierType) { + logger.info("createTradeDto(): Creating TradeDto with identifier type: {}", identifierType); + SecurityService securityService = new SecurityService(); + String securityIdentifier = securityService.getSecurityIdentifierOfType(trade.getSecurityID(), identifierType); + TradeDto tradeDto = new TradeDto(securityIdentifier); + return tradeDto; + } +} + + diff --git a/mapstruct-2/src/test/java/com/baeldung/context/mapper/MapperContextUnitTest.java b/mapstruct-2/src/test/java/com/baeldung/context/mapper/MapperContextUnitTest.java new file mode 100644 index 000000000000..4d58197087c5 --- /dev/null +++ b/mapstruct-2/src/test/java/com/baeldung/context/mapper/MapperContextUnitTest.java @@ -0,0 +1,44 @@ +package com.baeldung.context.mapper; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +import com.baeldung.context.entity.Trade; +import com.baeldung.context.entity.TradeDto; + +public class MapperContextUnitTest { + @Test + void givenBeforeMappingMethod_whenSecurityIdInTradeObject_thenSetSecurityIdentifierInTradeDto() { + Trade trade = createTradeObject(); + + TradeDto tradeDto = TradeMapperWithBeforeMapping.getInstance() + .toTradeDto(trade, "CUSIP", 6464); + + assertEquals("037833100", tradeDto.getSecurityIdentifier()); + } + + @Test + void givenAfterMappingMethod_whenSecurityIdInTradeObject_thenSetSecurityIdentifierInTradeDto() { + Trade trade = createTradeObject(); + + TradeDto tradeDto = TradeMapperWithAfterMapping.getInstance() + .toTradeDto(trade, "CUSIP"); + + assertEquals("037833100", tradeDto.getSecurityIdentifier()); + } + + @Test + void whenGivenSecurityIDInTradeObject_thenUseObjectFactoryToCreateTradeDto() { + Trade trade = createTradeObject(); + + TradeDto tradeDto = TradeMapperUsingObjectFactory.getInstance() + .toTradeDto(trade, "SEDOL"); + + assertEquals("B1Y8QX7", tradeDto.getSecurityIdentifier()); + } + + private Trade createTradeObject() { + return new Trade("AAPL", 100, 150.0); + } +}