GWT地图编辑器+验证器

时间:2014-11-18 11:01:26

标签: java gwt bean-validation

我面临以下情况:

让B和C编辑我正在编辑的bean,将B属性定义为Map:

public class B {
    @Valid
    private C c;

    @Valid
    private Map<String, C> map = new HashMap<String, C>();

    public Map<String, C> getMap() {
        return map;
    }

    public void setMap(Map<String, C> lista) {
        this.map = lista;
    }

    public B() {
    }

    public C getC() {
        return c;
    }

    public void setC(C c) {
        this.c = c;
    }
}

public class C {
    private Long id;

    @NotEmpty
    @Size(min=10)
    private String foo;

    @Min(value=100)
    private Integer pages;

    public C() {
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFoo() {
        return foo;
    }

    public void setFoo(String foo) {
        this.foo = foo;
    }

    public Integer getPages() {
        return pages;
    }

    public void setPages(Integer pages) {
        this.pages = pages;
    }
}

让BEditor,CEditor和CMapEditor编辑我用来编辑这些bean和map属性:

public class BEditor extends Composite implements Editor<B> {
    CMapEditor mapEditor;

    CEditor cEditor;

    public BEditor() {
        mapEditor = new CMapEditor();

        cEditor = new CEditor();

        VerticalLayoutContainer c = new VerticalLayoutContainer();            
        c.add(mapEditor, new VerticalLayoutData(-1, 0.5));
        c.add(cEditor, new VerticalLayoutData(-1, 0.5));        

        initWidget(c);
    }

}

public class CEditor extends Composite implements Editor<C>{
    TextField fooEditor;

    IntegerSpinnerField pagesEditor;

    public CEditor() {
        fooEditor = new TextField();

        pagesEditor = new IntegerSpinnerField();
        pagesEditor.setErrorSupport(new ToolTipErrorHandler(pagesEditor));

        VerticalLayoutContainer c = new VerticalLayoutContainer();            
        c.add(fooEditor, new VerticalLayoutData(1, -1));
        c.add(pagesEditor, new VerticalLayoutData(1, -1));

        initWidget(c);
    }
}

public class CMapEditor extends Composite implements ValueAwareEditor<Map<String, C>> {
    Map<String, CEditor> ceditors = new HashMap<String, CEditor>();
    private Map<String, C> value = new HashMap<String, C>();
    private String[] locales = { "en", "es" };

    public CMapEditor() {
        TabPanel tabPanel = new TabPanel();
        for (String locale : locales) {
            CEditor cEditor = new CEditor();

            ceditors.put(locale, cEditor);

            tabPanel.add(cEditor, locale);
        }
        initWidget(tabPanel);
    }

    @Override
    public void flush() {
        for (Entry<String, C> entry : value.entrySet()) {
            CEditor cEditor = ceditors.get(entry.getKey());

            C c = entry.getValue();
            c.setFoo(cEditor.fooEditor.getValue());
            c.setPages(cEditor.pagesEditor.getValue());
        }
    }

    @Override
    public void setValue(Map<String, C> value) {
        this.value = value;
        for (Entry<String, C> entry : value.entrySet()) {
            C c = entry.getValue();

            CEditor cEditor = ceditors.get(entry.getKey());
            cEditor.fooEditor.setValue(c.getFoo());
            cEditor.pagesEditor.setValue(c.getPages());
        }
    }

    @Override
    public void setDelegate(EditorDelegate<Map<String, C>> delegate) {
    }

    @Override
    public void onPropertyChange(String... paths) {
    }
}

当我开始编辑时,编辑器被正确填充。此外,刷新和验证工作正常(验证器返回我期望的所有违规),但是当我在驱动程序中设置违规时,这些违规的消息不会显示在CMapEditor组件的ErrorHandlers中:

// Create the Driver
Driver driver = GWT.create(Driver.class);

public void edit(B p) {
    BEditor editor = new BEditor();
    // Initialize the driver with the top-level editor
    driver.initialize(editor);
    // Copy the data in the object into the UI
    driver.edit(p);

    // Put the UI on the screen.
    Dialog dialogBox = new Dialog();
    dialogBox.setWidget(editor);
    dialogBox.setWidth("350px");
    dialogBox.setHeight("100px");
    dialogBox.getButton(PredefinedButton.OK).addSelectHandler(new SelectEvent.SelectHandler() {            
        @Override
        public void onSelect(SelectEvent event) {
            B edited = driver.flush();

            Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
            Set violations = validator.validate(edited);
            if (!violations.isEmpty() && driver.setConstraintViolations(violations));
                List<EditorError> errors = driver.getErrors();
                //...
        }
    });
    dialogBox.show();
}

我有什么样的黑魔法吗?有没有其他方法可以解决这种情况?

提前致谢

1 个答案:

答案 0 :(得分:1)

要么我没有得到它(还有更多的事情发生在我身上),或者你在这里错过了一大块难题 - 你的CMapEditor看起来并不像正在倾听错误,并且没有向驱动程序公开其子路径(请参阅ListEditor示例),因此您调用CEditors Editor的事实并不意味着它们是实际上是系统的一部分。您手动连接&#39; sub&#39; CMapEditor中的编辑器,这意味着你现在负责在需要调用它们时调用它们。

ListEditor扩展CompositeEditor,并为列表中的工作添加特定支持,让儿童编辑通过告诉总编辑系统他们以及他们对应的路径来参与编辑。您应该考虑扩展CompositeEditor,可能类似于CMapEditor implements CompositeEditor<Map<String, C>, C, CEditor>,或者添加像interface MapEditor<K, V, E extends Editor<? super V>> extends CompositeEditor<Map<K, V>, V, E>这样的中间可重用类型,并实现 来构建您自己的CMapEditor类型。

如果您没有连接新创建的CEditor对象,以便他们可以与代理或驱动程序通信(通常将其设为EditorIsEditor字段,还可以使用CompositeEditor.Chain工具,然后系统无法了解您的编辑,也无法调用它们。这提供了另一种选择:使CMapEditor也实现HasEditorErrors&lt; ...&gt;这样你就可以在整个地图上得到所有错误,并且可以将你自己传递给CEditor。显然,这将需要您更多的布线,并要求您保持最新状态,但这是权衡 - 如果您告诉编辑系统有关儿童编辑器,它会为您做,但如果它不知道它需要做什么就无法完成工作。