Module is.codion.framework.domain
Interface DerivedAttributeDefinition<T>
- Type Parameters:
T
- the underlying type
- All Superinterfaces:
AttributeDefinition<T>
A definition for attributes which value is derived from the values of one or more attributes.
DerivedAttributeDefinition configures attributes that compute their values from other attributes within the same entity or from related entities. These attributes provide calculated fields, formatting, aggregation, and other computed values.
Derived attributes can be cached for performance or computed on-demand:
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");
Column<String> PHONE = TYPE.stringColumn("phone");
// Derived attributes
Attribute<String> FULL_NAME = TYPE.stringAttribute("full_name");
Attribute<String> CONTACT_INFO = TYPE.stringAttribute("contact_info");
Attribute<Integer> AGE = TYPE.integerAttribute("age");
Attribute<String> NAME_UPPER = TYPE.stringAttribute("name_upper");
}
void defineCustomer() {
Customer.TYPE.define(
Customer.FIRST_NAME.define()
.column(),
Customer.LAST_NAME.define()
.column(),
Customer.EMAIL.define()
.column(),
Customer.BIRTH_DATE.define()
.column(),
Customer.PHONE.define()
.column(),
// Simple derived attribute (cached by default)
Customer.FULL_NAME.define()
.derived(Customer.FIRST_NAME, Customer.LAST_NAME)
.provider(sourceValues -> {
String first = sourceValues.get(Customer.FIRST_NAME);
String last = sourceValues.get(Customer.LAST_NAME);
if (first == null && last == null) {
return null;
}
return ((first != null ? first : "") + " " +
(last != null ? last : "")).trim();
})
.caption("Full Name"),
// Multi-source derived attribute with caching disabled
Customer.CONTACT_INFO.define()
.derived(Customer.FULL_NAME, Customer.EMAIL, Customer.PHONE)
.provider(sourceValues -> {
String name = sourceValues.get(Customer.FULL_NAME);
String email = sourceValues.get(Customer.EMAIL);
String phone = sourceValues.get(Customer.PHONE);
StringBuilder contact = new StringBuilder();
if (name != null) contact.append(name);
if (email != null) {
if (contact.length() > 0) contact.append(" - ");
contact.append(email);
}
if (phone != null) {
if (contact.length() > 0) contact.append(" - ");
contact.append(phone);
}
return contact.toString();
})
.cached(false) // Compute on each access
.caption("Contact Information"),
// Time-dependent derived attribute (not cached)
Customer.AGE.define()
.derived(Customer.BIRTH_DATE)
.provider(sourceValues -> {
LocalDate birthDate = sourceValues.get(Customer.BIRTH_DATE);
return birthDate != null ?
Period.between(birthDate, LocalDate.now()).getYears() : null;
})
.cached(false) // Age changes over time
.caption("Age"),
// Formatting derived attribute
Customer.NAME_UPPER.define()
.derived(Customer.FULL_NAME)
.provider(sourceValues -> {
String fullName = sourceValues.get(Customer.FULL_NAME);
return fullName != null ? fullName.toUpperCase() : null;
})
.caption("Name (Uppercase)"))
.build();
}
}
// Usage examples
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" (cached)
String contactInfo = customer.get(Customer.CONTACT_INFO); // Computed each time
Integer age = customer.get(Customer.AGE); // Current age
String nameUpper = customer.get(Customer.NAME_UPPER); // "JOHN DOE"
// Modifying source attributes updates derived values
customer.set(Customer.FIRST_NAME, "Jane");
String newFullName = customer.get(Customer.FULL_NAME); // "Jane Doe"
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeInterfaceDescriptionstatic interface
Builds a derived AttributeDefinition instanceNested classes/interfaces inherited from interface is.codion.framework.domain.entity.attribute.AttributeDefinition
AttributeDefinition.ValueSupplier<T>
-
Field Summary
Fields inherited from interface is.codion.framework.domain.entity.attribute.AttributeDefinition
DATE_FORMAT, DATE_TIME_FORMAT, DECIMAL_ROUNDING_MODE, DECIMAL_SEPARATOR, DEFAULT_MAXIMUM_FRACTION_DIGITS, GROUPING_SEPARATOR, MAXIMUM_FRACTION_DIGITS, MNEMONIC_RESOURCE_SUFFIX, NUMBER_FORMAT_GROUPING, TIME_FORMAT, TRIM_STRINGS, USE_LEXICAL_STRING_COMPARATOR
-
Method Summary
Modifier and TypeMethodDescriptionboolean
cached()
Note that cached attributes are included when an entity is serialized.Methods inherited from interface is.codion.framework.domain.entity.attribute.AttributeDefinition
attribute, caption, comparator, dateTimeFormatter, dateTimePattern, decimalRoundingMode, defaultValue, derived, description, entityType, format, hasDefaultValue, hidden, items, maximumFractionDigits, maximumLength, maximumValue, minimumValue, mnemonic, nullable, string, trim, validItem
-
Method Details
-
sourceAttributes
- Returns:
- the attributes this attribute derives from.
-
valueProvider
DerivedAttribute.Provider<T> valueProvider()- Returns:
- the value provider, providing the derived value
-
cached
boolean cached()Note that cached attributes are included when an entity is serialized.- Returns:
- true if the value of this derived attribute is cached, false if computed on each access
-