Interface DerivedAttribute<T>

Type Parameters:
T - the value type
All Superinterfaces:
Attribute<T>

public interface DerivedAttribute<T> extends Attribute<T>
An attribute which value is derived from one or more source attributes.

Derived attributes compute their values from other attributes within the same entity or from related entities. They provide calculated fields, formatting, concatenation, and other derived values without being stored in the database.

Derived attributes are defined using value providers that receive source values and compute the derived result:

 public class Store extends DefaultDomain {

     interface Customer {
         EntityType TYPE = DOMAIN.entityType("store.customer");

         Column<String> FIRST_NAME = TYPE.stringColumn("first_name");
         Column<String> LAST_NAME = TYPE.stringColumn("last_name");
         Column<String> EMAIL = TYPE.stringColumn("email");
         Column<LocalDate> BIRTH_DATE = TYPE.localDateColumn("birth_date");

         // Derived attributes
         Attribute<String> FULL_NAME = TYPE.stringAttribute("full_name");
         Attribute<String> DISPLAY_NAME = TYPE.stringAttribute("display_name");
         Attribute<Integer> AGE = TYPE.integerAttribute("age");
         Attribute<String> INITIALS = TYPE.stringAttribute("initials");
     }

     void defineCustomer() {
         Customer.TYPE.define(
                 Customer.FIRST_NAME.define()
                     .column(),
                 Customer.LAST_NAME.define()
                     .column(),
                 Customer.EMAIL.define()
                     .column(),
                 Customer.BIRTH_DATE.define()
                     .column(),

                 // Simple concatenation
                 Customer.FULL_NAME.define()
                     .attribute()
                     .derived(Customer.FIRST_NAME, Customer.LAST_NAME)
                     .provider(values -> {
                         String first = values.get(Customer.FIRST_NAME);
                         String last = values.get(Customer.LAST_NAME);
                         return (first != null ? first : "") + " " + (last != null ? last : "");
                     }),

                 // Complex formatting with multiple sources
                 Customer.DISPLAY_NAME.define()
                     .attribute()
                     .derived(Customer.FULL_NAME, Customer.EMAIL)
                     .provider(values -> {
                         String fullName = values.get(Customer.FULL_NAME);
                         String email = values.get(Customer.EMAIL);
                         return fullName + " (" + email + ")";
                     }),

                 // Age calculation
                 Customer.AGE.define()
                     .attribute()
                     .derived(Customer.BIRTH_DATE)
                     .provider(values -> {
                         LocalDate birthDate = values.get(Customer.BIRTH_DATE);
                         return birthDate != null ?
                             Period.between(birthDate, LocalDate.now()).getYears() : null;
                     }),

                 // Initials from names
                 Customer.INITIALS.define()
                     .attribute()
                     .derived(Customer.FIRST_NAME, Customer.LAST_NAME)
                     .provider(values -> {
                         String first = values.get(Customer.FIRST_NAME);
                         String last = values.get(Customer.LAST_NAME);
                         String firstInitial = first != null && !first.isEmpty() ?
                             first.substring(0, 1).toUpperCase() : "";
                         String lastInitial = last != null && !last.isEmpty() ?
                             last.substring(0, 1).toUpperCase() : "";
                         return firstInitial + lastInitial;
                     }))
             .build();
     }
 }

 // Usage
 Entity customer = entities.builder(Customer.TYPE)
     .with(Customer.FIRST_NAME, "John")
     .with(Customer.LAST_NAME, "Doe")
     .with(Customer.EMAIL, "john.doe@example.com")
     .with(Customer.BIRTH_DATE, LocalDate.of(1990, 5, 15))
     .build();

 // Derived values are computed automatically
 String fullName = customer.get(Customer.FULL_NAME);       // "John Doe"
 String displayName = customer.get(Customer.DISPLAY_NAME); // "John Doe (john.doe@example.com)"
 Integer age = customer.get(Customer.AGE);                 // Calculated age
 String initials = customer.get(Customer.INITIALS);       // "JD"
See Also: