0

This is an extension to this question.

 class Customer{
  // distinct properties
}
class RetailCustomer extends Customer{
  // distinct properties
}

class WholeSaleCustomer extends Customer{
 // distinct properties
}

class CustomerDO {
 // String custType ; // flag used to determine if Customer is wholeSale or Retail
 //few properties same as Customer/WholeSaleCustomer/RetailCustomer
 // few distinct properties
}

@Mapper
public interface CustomerMapper{

           default Customer toCustomer(CustomerDO customerDO) {
                 String custType = customerDO.getCustType();
                if("W".equalsIgnoreCase(custType)){
                   return toWholeSaleCustomer(customerDO);
                  }
                 else {
                  return toRetailCustomer(CustomerDO);
                   }
           }
        @Mappings({
              @Mapping(source="a", target="b"),
               @Mapping(source="c", target="d"),
               @Mapping(source="m", target="m")
            })
         WholeSaleCustomer toWholeSaleCustomer(CustomerDO customerDO);

       @Mappings({
              @Mapping(source="e", target="f"),
               @Mapping(source="g", target="h"),
               @Mapping(source="n", target="n")
            })
         RetailCustomer toRetailCustomer(CustomerDO customerDO);
}

I need to map from CustomerDO to WholeSaleCustomer/RetailCustomer based on custType flag in CustomerDO. But above defined mapper doesn't work. It gives me below error while compiling

 CustomerMapper.java:[23,34] Ambiguous mapping methods found for mapping property "com.domain.CustomerDO customerDO" to com.role.Customer: com.role.Customer: toCustomer
r(com.domain.CustomerDO customerDO), com.role.WholeSaleCustomer toWholeSaleCustomer(com.domain.CustomerDO wsCustomer), com.role.RetailCustomer toRetailCustomer(com.domain.CustomerDO wsCustomer)

But if I change toCustomer(CustomerDo customerDO) signature to toCustomer(Object customerDO) and remove either of toWholeSaleCustomer/toRetailCustomer, it works. It will only map either of two types. But I want both. I've similar case for Service Bean. There are serveral child Services. I should be able to map them all whenever they are required

Naveen
  • 403
  • 1
  • 6
  • 20

1 Answers1

0

What you are looking for is Mapping method selection based on qualifiers.

So if your customer objects look like:

class WholeSaleCustomer extends Customer {
 // distinct properties
}

class CustomerDO {
 // String custType ; // flag used to determine if Customer is wholeSale or Retail
 //few properties same as Customer/WholeSaleCustomer/RetailCustomer
 // few distinct properties
    private CustomerDO customerDO;
}

Then you would have to tell MapStruct which method it needs to use to perform the mapping. So your mapper would look like:

@Mapper
public interface CustomerMapper {

        @Named("baseCustomer")
        default Customer toCustomer(CustomerDO customerDO) {
            String custType = customerDO.getCustType();
            if("W".equalsIgnoreCase(custType)){
                return toWholeSaleCustomer(customerDO);
            }
            else {
                return toRetailCustomer(CustomerDO);
            }
        }

        @Mappings({
            @Mapping(source="customerDO", qualifiedByName = "baseCustomer"),
            @Mapping(source="c", target="d"),
            @Mapping(source="m", target="m")
        })
        WholeSaleCustomer toWholeSaleCustomer(CustomerDO customerDO);

        @Mappings({
            @Mapping(source="customerDO", qualifiedByName = "baseCustomer"),
            @Mapping(source="g", target="h"),
            @Mapping(source="n", target="n")
        })
        RetailCustomer toRetailCustomer(CustomerDO customerDO);
}

@Named should come from org.mapstruct.Named.

Filip
  • 19,269
  • 7
  • 51
  • 60
  • customerDO isn't a property of neither WholeSaleCustomer or RetailCustomer. Besides. I didn't understand what exactly you did there. It is not working anyway. It gives me compilation error saying attribute target is missing. I hope you understood my question clearly. Observation: All three methods in the mapper interface have same argument and same return type. If I change method arguments of to three different types, then there is no issue. Code is being generated. I'm not really sure whether this is an issue or I'm doing any mistake. – Naveen Apr 04 '18 at 18:14
  • They don't have the same return target. All of them are different. They just have the same source. Of course it would work if you change the types. Did you look in the documentation link I posted? Pleae update your question with the exact property for which you get the ambiguous mapping error – Filip Apr 04 '18 at 19:03
  • Yeah. But they have parent child relationship. I did look into the documentation. – Naveen Apr 05 '18 at 13:00
  • Please provide some more information for your types. Which property is the one where you get the error? – Filip Apr 05 '18 at 18:44