LabelValueBean.javaConcrete implementation of the Label/Value pattern. 89 lines. This is the most commonly used DTO in ProjectForge's UI layer — every dropdown, every autocomplete, every selection list is built from a List<LabelValueBean>. The "Label" is what the user sees (typically localized text); the "Value" is what the system stores (typically a Long ID or enum constant).
Class hierarchy: ILabelValueBean<L, V> (interface) → LabelValueBean<L extends Comparable<L>, V> (this class). Note the additional constraint vs the interface — L must be Comparable because the bean compares by label.
Key insight: LabelValueBean compares by label (this.label.compareTo(o.label)), while KeyValueBean compares by value. This is the fundamental semantic difference:
This means the type constraint is also on the label: L extends Comparable<L>. The value type V is unconstrained — it doesn't need to be comparable because the bean never compares values.
Unlike KeyValueBean (which is effectively immutable — no setters), LabelValueBean has a setValue(V) setter. The label has no setter but the field is protected — subclasses can modify it. This mutability matters because Wicket's form binding framework (PropertyModel) often needs to write back selected values into the bean — the dropdown selection sets the value via setValue(). KeyValueBean doesn't need this because it's used in read-only contexts (config display, chart labels).
Uses ToStringBuilder but with swapped field names (a minor bug): it prints key={value} and value={label} — the names "key" and "value" are from a copy-paste of KeyValueBean's toString. The actual data is correct (label and value are in the right positions), but the labels are misleading. This has zero functional impact — toString() is only used for debugging.
LabelValueBean() — empty for Wicket/XStream deserializationLabelValueBean(V value) — value-only (label defaults to null). Used when the label will be computed later or when value-is-also-labelLabelValueBean(L label, V value) — full constructor. Most commonly used: new LabelValueBean<>("John Doe", 42L)