Consider this case.
You have a class which you cannot change or extend in any way.
public class Foo {
...
private Boolean bar;
...
}
You need to edit the fields of that class via BeanEditor
, but the logic behind that class allows and uses the fact that Boolean
can have, so to say, 3 states: null, true and false.
Tapestry will, however, give you a checkbox with only 2 options, true or false.
So, people online suggest that you convert your Boolean
type property to BooleanExtendedEnum
type property which could represent three way logic.
public enum BooleanExtendedEnum {
UNDEFINED(null),
TRUE(Boolean.TRUE),
FALSE(Boolean.FALSE);
private Boolean booleanValue;
private static Map<Boolean, BooleanExtendedEnum> booleanToExtendedMap = new HashMap<Boolean, BooleanExtendedEnum>();
static {
for (BooleanExtendedEnum be : BooleanExtendedEnum.values()) {
booleanToExtendedMap.put(be.booleanValue, be);
}
}
private BooleanExtendedEnum(Boolean booleanValue) {
this.booleanValue = booleanValue;
}
public Boolean getBooleanValue() {
return booleanValue;
}
public static BooleanExtendedEnum getBooleanExtendedValue(Boolean booleanInput) {
return booleanToExtendedMap.get(booleanInput);
}
}
Since you cannot change your Foo
class, you'll need to create a coercer for Boolean <=> BooleanExtendedEnum
.
Coercion<Boolean, BooleanExtendedEnum> threeWayBooleanToExtended = new Coercion<Boolean, BooleanExtendedEnum>() {
@Override
public BooleanExtendedEnum coerce(Boolean input) {
if (input == null) {
return BooleanExtendedEnum.UNDEFINED;
} else {
return BooleanExtendedEnum.getBooleanExtendedEnumValue(input);
}
}
};
Coercion<BooleanExtendedEnum, Boolean> threeWayExtendedToBoolean = new Coercion<BooleanExtendedEnum, Boolean>() {
@Override
public Boolean coerce(BooleanExtendedEnum input) {
if (input == null) {
return null;
} else {
return input.getBooleanValue();
}
}
};
configuration.add(new CoercionTuple<Boolean, BooleanExtendedEnum>(Boolean.class, BooleanExtendedEnum.class, threeWayBooleanToExtended));
configuration.add(new CoercionTuple<BooleanExtendedEnum, Boolean>(BooleanExtendedEnum.class, Boolean.class, threeWayExtendedToBoolean));
Let's assume you have done something as simple as this in your BeanEditor
in your tml
:
<p:bar>
<div class="t-beaneditor-row">
<label>Bar Value</label>
<t:select t:id="fooBar" t:value="foo.bar" t:model="booleanExtendedSelectModel" t:blankOption="NEVER"/>
</div>
</p:bar>
... and provided the SelectModel
like this:
public SelectModel getBooleanExtendedSelectModel() {
return new EnumSelectModel(BooleanExtendedEnum.class, messages);
}
Tapestry will create a drop-down list with three options
However, the real Boolean values it will coerce those displayed values to will be
Undefined
-> true
True
-> true
False
-> false
How can one achieve the desired effect (Undefined
-> null), with limitations of not changing the class or wrapping it in another class which has Boolean
type fields replaced with BooleanExtendedEnum
type ones or using any other "hacky" solution?