2

この場合を考えてみましょう。

いかなる方法でも変更または拡張できないクラスがあります。

public class Foo {
    ...
    private Boolean bar;
    ...
}

を介してそのクラスのフィールドを編集する必要がありますが、そのクラスBeanEditorの背後にあるロジックでは、nulltrue、およびfalseBooleanの3 つの状態を持つことができるという事実が許可され、使用されます。

ただし、Tapestry はtrueまたはfalseの 2 つのオプションしかないチェックボックスを提供します。

そのため、オンラインの人々は、タイプ プロパティを 3 方向ロジックを表すタイプBooleanプロパティに変換することを提案しています。BooleanExtendedEnum

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);
    }

}

クラスを変更することはできないFooため、 の coercer を作成する必要があります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));

BeanEditorで次のような簡単なことをしたとしましょう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>

...そして次のSelectModelようなものを提供しました:

public SelectModel getBooleanExtendedSelectModel() {
    return new EnumSelectModel(BooleanExtendedEnum.class, messages);
}

Tapestry は 3 つのオプションを含むドロップダウン リストを作成します

  • Undefined
  • True
  • False

ただし、表示された値を強制する実際のブール値は次のようになります。

  • Undefined->
  • True->
  • False->

クラスを変更したり、型フィールドが型フィールドに置き換えられた別のクラスにラップしたり、他の「ハッキー」ソリューションを使用したりしないという制限付きで、目的の効果 ( Undefined-> null ) をどのように達成できますか?BooleanBooleanExtendedEnum

4

2 に答える 2

1

ページにプロパティを追加して、カスタム ブロックを使用できます。

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>
于 2014-02-19T14:52:10.947 に答える
1

BeanEditor とバッキング Bean の間の「接着剤」はBeanModelです。BeanModel は、 PropertyConduitSourceを使用する BeanModelSource によって作成されます。

Ternaryの代わりに使用するために PropertyConduitSource を装飾するのは非常に簡単ですBoolean

例えば

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);
   }
}
于 2014-02-20T08:39:41.413 に答える