Java 如何覆盖Tapestry';s双向布尔强制与三向一?
考虑一下这个例子 您有一个不能以任何方式更改或扩展的类Java 如何覆盖Tapestry';s双向布尔强制与三向一?,java,null,boolean,tapestry,coercion,Java,Null,Boolean,Tapestry,Coercion,考虑一下这个例子 您有一个不能以任何方式更改或扩展的类 public class Foo { ... private Boolean bar; ... } 您需要通过BeanEditor编辑该类的字段,但该类背后的逻辑允许并使用Boolean可以有三种状态:null、true和false 然而,Tapestry将为您提供一个只有两个选项的复选框,true或false 因此,在线人士建议您将Booleantype属性转换为BooleanExtendedEnumtype属性
public class Foo {
...
private Boolean bar;
...
}
您需要通过BeanEditor
编辑该类的字段,但该类背后的逻辑允许并使用Boolean
可以有三种状态:null、true和false
然而,Tapestry将为您提供一个只有两个选项的复选框,true或false
因此,在线人士建议您将Boolean
type属性转换为BooleanExtendedEnum
type属性,该属性可以表示三向逻辑
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);
}
}
让我们假设您在tml
中的BeanEditor
中做了这样简单的事情:
<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>
Tapestry将创建一个包含三个选项的下拉列表
未定义
True
False
->正确未定义
->TrueTrue
->FalseFalse
如何实现所需的效果(
未定义
->空),而不更改类或将其包装到另一个类中,该类的布尔
类型字段替换为布尔扩展枚举
类型字段或使用任何其他“hacky”类型字段解决方案?您可以向页面添加属性并使用自定义块
public enum Ternary {
TRUE(Boolean.TRUE), FALSE(Boolean.FALSE), UNDEFINED(null);
public static Ternary valueOf(Boolean value) { ... }
public Boolean asBoolean() { ... }
}
public class MyPage {
@Property
private Foo foo;
public Ternary getTernaryBar() {
return Ternary.valueOf(foo.getBar());
}
public void setTernaryBar(Ternary tBar) {
foo.setBar(tBar.asBoolean());
}
}
<t:beaneditor t:id="foo" exclude="bar" add="ternaryBar">
<p:ternaryBar>
<t:label for="ternaryBar"/>
<t:select t:id="ternaryBar" />
</p:ternaryBar>
</t:beaneditor>
公共枚举{
TRUE(Boolean.TRUE)、FALSE(Boolean.FALSE)、未定义(null);
公共静态三元值(布尔值){…}
公共布尔值asBoolean(){…}
}
公共类MyPage{
@财产
私人富福;
公共三元getTernaryBar(){
返回三元.valueOf(foo.getBar());
}
公共无效设置栏(待定){
foo.setBar(tBar.asBoolean());
}
}
BeaneEditor和支持bean之间的“粘合剂”是。BeanModel由BeanModelSource创建,BeanModelSource反过来使用
使用三元
而不是布尔
来修饰PropertyConduitSource非常简单
乙二醇
我理解这个解决方案,但考虑到我在相当多的页面上有相当多的Foo类,这不是我正在寻找的解决方案。尽管如此,thx的努力:)这看起来很有趣,你可能有一个链接到一些例子?我相信我理解你在这里说的话,但因为我以前从未做过,我想确定:)我也从未做过。我已经为您提供了装饰方法的领先优势,但您需要实现TernaryBeanModelSource。添加了更改。现在简单多了啊,sry,没有看到你添加了更改,tyvm:)我也朝着类似的方向走,但是是的,这简单多了:)看来我还有很多关于Tapestry的知识要学。和往常一样,我非常感谢:DIt是一个自定义注释,您可以创建并命名您喜欢的方式
public SelectModel getBooleanExtendedSelectModel() {
return new EnumSelectModel(BooleanExtendedEnum.class, messages);
}
public enum Ternary {
TRUE(Boolean.TRUE), FALSE(Boolean.FALSE), UNDEFINED(null);
public static Ternary valueOf(Boolean value) { ... }
public Boolean asBoolean() { ... }
}
public class MyPage {
@Property
private Foo foo;
public Ternary getTernaryBar() {
return Ternary.valueOf(foo.getBar());
}
public void setTernaryBar(Ternary tBar) {
foo.setBar(tBar.asBoolean());
}
}
<t:beaneditor t:id="foo" exclude="bar" add="ternaryBar">
<p:ternaryBar>
<t:label for="ternaryBar"/>
<t:select t:id="ternaryBar" />
</p:ternaryBar>
</t:beaneditor>
public class MyAppModule {
public PropertyConduitSource decoratePropertyConduitSource(final PropertyConduitSource old) {
return new PropertyConduitSource() {
public PropertyConduit create(Class rootType, String expression) {
PropertyConduit conduit = old.create(rootType, expression);
// you cound also check for conduit.getAnnotation(AllowNull.class)
// and then annotate your bean properties for a more granular approach
if (Boolean.class.equals(conduit.getPropertyType()) {
return new TernaryPropertyConduit(conduit);
}
return conduit;
}
}
}
}
public class TernaryPropertyConduit implements PropertyConduit {
private PropertyConduit delegate;
public getPropertyType() { return Ternary.class };
public set(Object instance, Object value) {
delegate.set(instance, ((Ternary) value).asBoolean());
}
public get(Object) {
Boolean bValue = (Boolean) delegate.get(instance);
return Ternary.valueOf(instance);
}
}