Primefaces 具有DefaultTreeNode子类的p:treenode的奇怪行为
我尝试在PrimeFaces4.0的动态模式下与持久化API一起使用p:tree。 我有@Entity类(Nomen),它已经有了引用自身的元素。我尝试了两种变体:在Nomen类接口TreeNode中实现,并使其成为DefaultTreeNode的子类。最后一个变体扩展了DefaultTreeNode。行为也是如此Primefaces 具有DefaultTreeNode子类的p:treenode的奇怪行为,primefaces,treenode,Primefaces,Treenode,我尝试在PrimeFaces4.0的动态模式下与持久化API一起使用p:tree。 我有@Entity类(Nomen),它已经有了引用自身的元素。我尝试了两种变体:在Nomen类接口TreeNode中实现,并使其成为DefaultTreeNode的子类。最后一个变体扩展了DefaultTreeNode。行为也是如此 @Entity @Table(name = "Nomen") public class Nomen extends DefaultTreeNode implements Serial
@Entity
@Table(name = "Nomen")
public class Nomen extends DefaultTreeNode implements Serializable {
@Id
private Integer id;
...
@Column(name = "Name")
private String name;
...
@JoinColumn(name = "Self_Id", referencedColumnName = "Id")
@ManyToOne
private Nomen parent;
@OneToMany(mappedBy = "parent", fetch=FetchType.EAGER)
private List<Nomen> nomenCollection;
...
public Nomen() {
super();
}
...
@Override
public String getType() {
if (nomenCollection == null) return "NomenLeaf";
return "NomenGroup";
}
@Override
public Nomen getData() {
Logger.getLogger(this.getClass().getName()).log(Level.INFO, "getData for {0}", new Object[] {this});
return this;
}
@Override
public Nomen getParent() {
return this.parent;
}
@Override
public void setParent(TreeNode tn) {
if (!(tn instanceof Nomen)) {
return;
}
try {
parent.removeChild(this);
}
catch (NullPointerException e) { }// Nothing to do
if (tn != null) {
((Nomen)tn).addChild(this);
}
parent = (Nomen)tn;
}
@Override
public int getChildCount() {
if (nomenCollection == null) return 0;
return nomenCollection.size();
}
@Override
public boolean isLeaf() {
return nomenCollection == null;
}
@Override
public String getRowKey() {
Logger.getLogger(this.getClass().getName()).log(Level.INFO, "getRowKey: this: {0} id: {1}", new Object[] {this, Integer.toString(getId())} );
return Integer.toString(getId());
}
@Override
public List<TreeNode> getChildren() {
// return new ArrayList<TreeNode> (nomenCollection);
// return (List<TreeNode>)(List<? extends TreeNode>)nomenCollection;
ArrayList<TreeNode> r = new ArrayList<> ();
for (Nomen n : nomenCollection) {
r.add(n);
}
Logger.getLogger(this.getClass().getName()).log(Level.INFO, "getChildren for {0}: List: {1} ", new Object[] {this, r});
return r;
}
public List<Nomen> getNomenCollection() {
return nomenCollection;
}
public void setNomenCollection (List<Nomen> n) {
nomenCollection = n;
}
}
电话的顺序似乎很奇怪
有人能帮忙吗?这个问题可以通过注释掉下面的代码来解决
/*
@Override
public String getRowKey() {
Logger.getLogger(this.getClass().getName()).log(Level.INFO, "getRowKey: this: {0} id: {1}", new Object[] {this, Integer.toString(getId())} );
return Integer.toString(getId());
}
*/
我当然不知道p:tree是如何使用getRowKey的。很可能,它必须以某种方式对应于p:tree的datakey属性。我还没有深入研究它们应该如何协同工作的文档。但调用序列中的所有混乱都是由重写getRowKey()引起的
谢谢大家的阅读 挖掘DefaultTreeNode的源代码发现了一些微妙的特性,这些特性在可用的文档中没有得到很好的反映 首先,我指的是特殊(我认为一般)用例:我有@Entity类,它已经包含引用自身的元素。我尝试为该类实现层次编辑器。几年前论坛上有人建议使用DefaultTreeNode子类,我决定也这样做。一些基本的东西在文档中被遗漏了,我不得不研究p的真实生物:树和树节点。在这里,如果有人需要的话,我试着描述这些细微的特征
<p:tree id="ntree" value="#{treeController.root}" var="nod" draggable="true" droppable="true" dynamic="true">
<p:ajax event="dragdrop" listener="#{treeController.onDragDrop}" update="@this">
...
</p:tree>
<p:draggable for="ntree" handle=".ui-treenode-label, .ui-treenode-icon"/>
<p:droppable for="ntree"/>
...
<p:ajax event="dragdrop" ...
<p:tree id="ntree" value="#{treeController.root}" var="nod" draggable="true" droppable="true" dynamic="true">
<p:ajax event="dragdrop" listener="#{treeController.onDragDrop}" update="@this">
...
</p:tree>
<p:draggable for="ntree" handle=".ui-treenode-label, .ui-treenode-icon"/>
<p:droppable for="ntree"/>
<p:ajax event="dragdrop" ...
public abstract class AbstractTreeNode<T> extends DefaultTreeNode {
@Override
public abstract String getType();
@Override
public abstract AbstractTreeNode<T> getParent();
@Override
public abstract void setParent(TreeNode tn);
@Override
public abstract List<TreeNode> getChildren();
public AbstractTreeNode() { super(); }
@Override
public T getData() {
return (T)this;
}
@Override
public int getChildCount() {
if (getChildren() == null) return 0;
return getChildren().size();
}
@Override
public boolean isLeaf() {
return (getChildren() == null) || getChildren().isEmpty();
}
@Override
public final String getRowKey() {
String r;
if (getParent() == null) r = "";
else if (getParent().getParent() == null)
r = ""+getParent().getChildren().indexOf(this);
else {
r = getParent().getRowKey() + "_" + getParent().getChildren().indexOf(this);
}
return r;
}
}
@Entity
public class SomeTable extends AbstractTreeNode<SomeTable> implements Serializable {
...