Module is.codion.framework.domain
Interface DerivedValue<T>
- Type Parameters:
T
- the value type
- All Superinterfaces:
Serializable
Responsible for providing values derived from other attribute values.
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)
.value(source -> {
String first = source.get(Customer.FIRST_NAME);
String last = source.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)
.value(source -> {
String fullName = source.get(Customer.FULL_NAME);
String email = source.get(Customer.EMAIL);
return fullName + " (" + email + ")";
}),
// Age calculation
Customer.AGE.define()
.attribute()
.derived(Customer.BIRTH_DATE)
.value(source -> {
LocalDate birthDate = source.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)
.value(source -> {
String first = source.get(Customer.FIRST_NAME);
String last = source.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.entity(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:
-
Nested Class Summary
Nested ClassesModifier and TypeInterfaceDescriptionstatic interface
Provides the source values from which to derive a value. -
Method Summary
Modifier and TypeMethodDescriptionget
(DerivedValue.SourceValues source) static DerivedValue.SourceValues
sourceValues
(Attribute<?> derivedAttribute, Map<Attribute<?>, Object> values)
-
Method Details
-
get
- Parameters:
source
- the source values, mapped to their respective attributes- Returns:
- the derived value
-
sourceValues
static DerivedValue.SourceValues sourceValues(Attribute<?> derivedAttribute, Map<Attribute<?>, Object> values) - Parameters:
derivedAttribute
- the derived attributevalues
- the values- Returns:
- a new
DerivedValue.SourceValues
instance
-