Search code examples
javagwttreecellobjectify

Gwt CellTree isLeaf() problem


I'm trying to display a tree of Categories, following the basic CellTree gwt examples.

What I am stuck at is determining the "leaf" condition of a Category.

A Category "is-a-leaf" when it hasn't children, right? So, here's my Category (I am using Objectify for appengine persistence):

@Entity
public class Categoria implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    Long id;

    String nome;    
    Key<Categoria> parent;

    public Categoria() { }

    public Categoria(String nome) {
        super();
        this.nome = nome;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public Key<Categoria> getParent() {
        return parent;
    }

    public void setParent(Key<Categoria> parent) {
        this.parent = parent;
    }
}

My TreeViewModel is based on AsyncDataProvider (which I pass from outside):

public class CategorieTreeViewModel implements TreeViewModel {

    private AbstractDataProvider<Categoria> dataProvider;

    public CategorieTreeViewModel(AbstractDataProvider<Categoria> dataProvider) {
        this.dataProvider = dataProvider;
    }

    @Override
    public <T> NodeInfo<?> getNodeInfo(T value) {
        return new DefaultNodeInfo<Categoria>(dataProvider, new CategoriaCell());
    }

    @Override
    public boolean isLeaf(Object value) {
        return false;
    }
}

So here it is:

dataProvider = new AsyncDataProvider<Categoria>() {         
            @Override
            protected void onRangeChanged(HasData<Categoria> display) {
                updateTree();
            }
        };

private void updateTree() {
        rpcService.getCategorie(new AsyncCallback<Categoria[]>() {
            @Override
            public void onSuccess(Categoria[] result) {
                dataProvider.updateRowCount(result.length, true);
                dataProvider.updateRowData(0, Arrays.asList(result));
            }
            @Override
            public void onFailure(Throwable caught) {
                Window.alert(caught.toString());
            }
        });
    }

The question is: since I don't have a "leaf property" on my Category bean, how can I know if it has children or not? By doing a query obviously, but the isLeaf method needs to return synchronously, how can I make my rpc call?

Or I can retrieve that "leaf" information in the getCategorie() call, filling the property at runtime, but this could be a performance problem.

What can I do?


Solution

  • I would add a transient property to the Categoria class, a boolean isLeaf, then inside the setParent method, you could set the parent's isLeaf property to false (because if this object has a parent of that, then that object is not a leaf). Making the property transient means it won't be persisted, so you don't have to worry about having that field in your data model.

    EDIT: Here is how I would code the Categoria class's setParent method...

    public void setParent(Key<Categoria> parent) {
        this.parent = parent;
        parent.setIsLeaf(false);
    }
    

    That way, once you have built up your model of Categoria nodes, each one of them knows whether it is a leaf or not. This works because if parent has this as a child, parent can't possibly be a leaf. Default the isLeaf property to true and you'll know if any given Categoria is a leaf just by checking it's property.