javalombok

Lombok instance copy from super with builder


I have these two classes with lombok Annotations:

@Data
@SuperBuilder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class Parent {
  private String id
  private Long field1;
  private Long field2;
  private Long field3;
}

and

@Data
@EqualsAndHashCode(callSuper = true)
@SuperBuilder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class Child extends Parent {
  private Integer prop1;
  private Integer prop2;
  private Integer prop3;
}

I would like to use an existent Parent instance to create a child instance, with all parent fields filled, and be able to complement with child properties (like Child.fromParent(parent).prop1(10).build()).

Is there a way to do it with lombok features, instead of a parent's "field by field" solution ?


Solution

  • You can indeed reuse some of the code that Lombok generates. In particular, Lombok generates a static method called $fillValuesFromInstanceIntoBuilder, which takes an instance and a builder, and populates the builder with the properties in the instance. This method is private, so you need to write a public wrapper around that.

    @Data
    @SuperBuilder(toBuilder = true)
    @NoArgsConstructor
    @AllArgsConstructor
    public class Parent {
        private String id;
        private Long field1;
        private Long field2;
        private Long field3;
    
        public static abstract class ParentBuilder<C extends Parent, B extends ParentBuilder<C, B>> {
            public static void fillValuesFromInstanceIntoBuilder(Parent instance, ParentBuilder<?, ?> b) {
                $fillValuesFromInstanceIntoBuilder(instance, b);
            }
        }
    }
    

    Then you can write a fromParent in Child like this:

    public static ChildBuilder<?, ?> fromParent(Parent parent) {
        var childBuilder = new ChildBuilderImpl();
        ParentBuilder.fillValuesFromInstanceIntoBuilder(parent, childBuilder);
        return childBuilder;
    }
    

    It is important to note that if you pass an instance of Child to fromParent, only the Parent fields will be copied to the builder. The fields specific to Child will be ignored.