Java Immutables merge object creation from optional fields

297 Views Asked by At

I'm working on a command line tool and I'm trying to minimize the amount of user input, but maximize the functionality. I've started going down the road of having a set of default inputs in the resources folder which allow the code to run with no user inputs at all. I'm handling this using the immutables library, so I have a type like this (Mickey Mouse example):

@Value.Immutable
public interface Type {
    String string();
    Double number();
    Boolean bool();
}

If I want the user to be able to override none, some or all of these values, I have another type with the same field, but wrapped in optionals.

@Value.Immutable
public interface OptionalType {
    Optional<String> string();
    Optional<Double> number();
    Optional<Boolean> bool();
}

When I want to merge the two types I have a method that checks the optional type field by field and rebuilds the non-optional type.

    public Type MergeType(Type type, OptionalType optionalType) {

        ImmutableType.Builder builder = ImmutableType.builder().from(type);

        if (optionalType.string().isPresent()){
            builder.string(optionalType.string().orElseThrow());
        }

        if (optionalType.number().isPresent()){
            builder.number(optionalType.number().orElseThrow());
        }

        if (optionalType.bool().isPresent()){
            builder.bool(optionalType.bool().orElseThrow());
        }

        return builder.build();
    }

This all works fine, however it's a lot of boiler plate code and I'm wondering if I'm better off taking a different route. It becomes quite cumbersome when there are 10+ fields in 10+ types. I've considered using reflection, but I'm always a bit weary of that as it usually means I'm a pattern of some kind.

1

There are 1 best solutions below

0
On

What comes to my mind is a feature of Optional, not Immutables itself

    public Type mergeType(Type type, OptionalType optionalType) {

        ImmutableType.Builder builder = ImmutableType.builder().from(type);

        optionalType.string().ifPresent(builder::string));
        optionalType.number().ifPresent(builder::number));
        optionalType.bool().ifPresent(builder::bool));
        
        return builder.build();
    }

you still to have to go through all parameters but there is less boilerplate and code is less error prone.

With development tool that allow column selection creating the code should not be very painful.

I renamed method name to lower case, to match Java convention.