hatellla
hatellla

Reputation: 5142

How to make the Java code generic for handling different kind of POJOS and adding data to that?

I have different kind of Customer POJO. And I have a function which takes customer details in a string format and take the type of the customer as well. Now, with this function I wanted to add the some information to it and then return the JSON string. I can do it by checking for type and deserializing to appropriate objects and handle it. But I wanted to figure out some way of refactoring which can do this without knowing the type of customers.

Following are my classes:

@Value.Immutable
public interface Customer1 {

    String firstName();

    String phoneNumber();

    @Value.Immutable
    interface Address1 {
        String addressLine();
    }
}

========

@Value.Immutable
public interface Customer2 {

    String firstName();

    String lastName();

    @Value.Immutable
    interface Address2 {
        String addressLine();

        String addressLine2();
    }
}

========

public enum CustomerType {
    CUSTOMER1(Customer1.class, Customer1.Address1.class),
    CUSTOMER2(Customer2.class, Customer2.Address2.class);

    private final Class<?> type;

    private final Optional<Class<?>> addressType;

    CustomerType(final Class<?> type) {
        this.type = type;
        this.addressType = Optional.empty();
    }

    CustomerType(final Class<?> type, final Class<?> addressType) {
        this.type = type;
        this.addressType = Optional.of(addressType);
    }

    public Class<?> getType() {
        return type;
    }

    public Optional<Class<?>> getAddressType() {
        return addressType;
    }
}

========

    private static final Gson GSON;

public String check(String customerType, String customerDetails, String addressDetails) {
    // Write this function such that it doesn't have to do check on what is customer Type.

    if (CustomerType.CUSTOMER1.name().equals(type)) {

        Customer1.Address1 address1 = GSON.fromJson(addressDetails, Customer1.Address1.class);

        Customer1 updatedCustomerDetails = ImmutableCustomer1.copyOf(GSON.fromJson(customerDetails, Customer1.class))
                .withAddress1(address1);

        return GSON.toJson(updatedCustomerDetails);
    } else if (CustomerType.CUSTOMER2.name().equals(type)) {
        /// Similar like above
    } else {
        return null;
    }

Is there any way I can generalize my check function using the CustomerType library? I am ready to refactor my code to any level. Probably my current model of Customer is wrong which makes me not do that easily.

Upvotes: 0

Views: 91

Answers (1)

racraman
racraman

Reputation: 5034

Firstly, determine what type of customer (ie, which value of CustomerType) you are dealing with. With that in hand, you can use a switch statement to determine processing (and ideally you can move each type's processing out to a separate method). Importantly, using such a switch statement can then trigger a build-time-error if any CustomerTypes are missing - better to catch that problem at build time than finding out some time later from an obscure runtime bug report !

public String check(String customerType, String customerDetails, String addressDetails) 
{

    try {
        CustomerType customerType = CustomerType.valueOf(type);
    } catch (IllegalArgumentException e) {
        return null;
    } 

    // Java12 - Use Switch Expressions
    String result = 
        switch (customerType) {
            case CUSTOMER1 -> formatCustomer1(customerDetails, addressDetails);
            case CUSTOMER2 -> formatCustomer2(customerDetails, addressDetails);
            // etc
         }


    // Up to Java 11 - Use normal Switch statement
    String result = null;
    switch (customerType) {
        case CUSTOMER1: result = formatCustomer1(customerDetails, addressDetails);
                        break;
        case CUSTOMER2: result = formatCustomer2(customerDetails, addressDetails);
                        break;
        // etc
     }

Java12's Switch Expressions have a few advantages :

1) Much cleaner syntax (not least, no "break" statements !)

2) Compile time error if not all enums are handled.

However, even the pre-Java12 switch has :

1) Your IDE will probably warn you if any enum values are missing

2) You can use automated tools that will fire a build-time-failure if enum values are missing

You could also take this a step further, and add methods to the CustomerType enum itself to call those "format" methods (although personally I think that could be taking things a step too far).

Upvotes: 1

Related Questions