`
hekui1016
  • 浏览: 50027 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Creating your own TreeModel in ADF 11g

    博客分类:
  • ADF
 
阅读更多

转自http://www.yonaweb.be/creating_your_own_treemodel_adf_11g_0

published by Yannick on 22 February, 2011 - 08:20

 

Building your own tree in ADF does not seem that easy at first sight but in fact it is not that hard if you know what to do. On the forum at OTN you often find questions about building your own model.

In this post you will find the steps needed to build your own model. In the example i just use some static data but you can rewrite it to use whatever you want.

We will build a tree that has 2 nodes in the root and the first node has 2 children.

Our TreeModel contains objects of the type TreeItem. TreeItem is not a build in class. I call it TreeItem but you can name it whatever you want. It is a regular bean with getters and setters. In order to build a tree, the class should have a method that returns its children.
This is the TreeItem class we will be using:

 

public class TreeItem {
    private String text,action;
    private List<TreeItem> children;
   
    public TreeItem() {
        super();
    }
   
    public TreeItem(String text,String action){
      super();
      this.text = text;
      this.action = action;
    }
 
    public void setText(String text) {
        this.text = text;
    }
 
    public String getText() {
        return text;
    }
 
    public void setAction(String action) {
        this.action = action;
    }
 
    public String getAction() {
        return action;
    }
 
    public void setChildren(List<TreeItem> children) {
        this.children = children;
    }
 
    public List<TreeItem> getChildren() {
        return children;
    }
}

 As you can see, the TreeItem has 3 properties:

 

  • text: containing the text that we will be using to show the node in the tree
  • action: this is the action that will be set to the action property of the commandLink in the tree. This way we can use the tree for navigation.
  • children: this contains a list of the children of the current node. This is vital for building a tree.

You are free to add more properties. Every property you add to the TreeItem you can use it in the tree itself.

Next we need to create our managed bean. This will contain the TreeModel itself.
In fact we just create the rootNode and use a default TreeModel from ADF. This is the ChildPropertyTreeModel.

We will build the tree in the constructor of the bean:

public TreeExample() {
        root = new ArrayList<TreeItem>();
        TreeItem node1 = new TreeItem("Node1","node1");
        TreeItem node2 = new TreeItem("Node2","node2");
        root.add(node1);
        root.add(node2);
       
        ArrayList<TreeItem> node1Children = new ArrayList<TreeItem>();
        TreeItem node1Child1 = new TreeItem("Child 1","child1");
        TreeItem node1Child2 = new TreeItem("Child 2","child2");
      node1Children.add(node1Child1);
      node1Children.add(node1Child2);
      node1.setChildren(node1Children);
     
      setListInstance(root);
    }
 
  public void setListInstance(List instance) {
    this.instance = instance;
    model = null;
  }

 The af:tree component requires a TreeModel as value so we need to create such a property as well:

public TreeModel getModel() {
    if(model == null)
        model = new ChildPropertyTreeModel(instance,"children");
    return model;
  }
 In this methode we will create the actual TreeModel based upon the root we created in the constructor. As you can see we also need to specify the name of the method that will return the children. By specifying "children" as a second parameter of the ChildPropertyTreeModel constructor, we tell the framework to call getChildren() in order to retreive the list of children.

When this is done, we need to register the bean to the faces-config.xml:

<managed-bean>
    <managed-bean-name>TreeExample</managed-bean-name>
    <managed-bean-class>view.beans.TreeExample</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>

 As a final step we need to add the tree to the page:

<af:tree value="#{TreeExample.model}" var="node">
   <f:facet name="nodeStamp">
      <af:commandLink text="#{node.text}" action="#{node.action}"/>
  </f:facet>
</af:tree>

 

另附一篇文章:

Back to programming: Programmatic ADF Faces Tree component

http://one-size-doesnt-fit-all.blogspot.com/2007/05/back-to-programming-programmatic-adf.html

Typically ADF Faces components in our JDeveloper 10.1.3 applications are data bound, meaning they map to objects in the binding layer as specified in separate pageDef files. This is expressed in our components through EL references to bindings}.

However what if we don't want to map to a binding layer object, but instead want to construct the data elements programmatically? For this blog we'll consider the example of an <af:tree> component to demonstrate this, showing how we construct the elements in the tree programmatically rather than relying on bindings.

Our goal is to construct an <af:tree> component comprised of <af:goLink> tags and looks as follows:

Logically understanding our hierarchy

Before we consider the <af:tree> component specifically, have a think about what the hierarchy represents. Each node in the tree has a text title, and a hyperlink destination. Each node is a child to a parent node, and each node may be comprised of 0, 1 or more child nodes. Collectively this represents our tree and is a simple logical concept.

Understanding the ADF Faces Tree component

The code for an <af:tree> in a web page would typically look as follows:

<af:tree var="node" value="#{treeModel.model}">
  <f:facet name="nodeStamp">
    <af:goLink text="#{node.text}" destination="#{node.destination}"/>
  </f:facet>
</af:tree>


In our example you'll note that the nodes within the tree are comprised of <af:goLink> tags that render the links in our tree above. You'll also note if you constructed a <af:tree> tag using the drag n drop facilities of JDeveloper based on a data bound component from the data control palette, the code would look very similar. In other words there isn't anything really special about the code above besides the use of <af:goLink> tags.

The <af:tree value> attribute demands at runtime an oracle.adf.view.faces.model.TreeModel instance. This class is the data model for the ADF Faces Tree component, where rows in the tree may contain other trees, or alternatively described, nodes in the tree can contain children nodes which in turn can also have children nodes and so on.

The nodeStamp facet of the <af:tree> walks the TreeModel, creating for each node the subtags contained within the <f:facet> tag, in this case an <af:goLink> tag. You'll note the <af:goLink> tag makes reference to the current node in the TreeModel as it walks the tree via the <af:tree> tag's var="node" attribute.

So we now logically have an understanding of what we want to model, and we also understand what the <af:tree> component wants. Lets consider our design solution.

Keeping it simple with a POJO

From the design point of view, to model the hierarchy we'd like to create our own very simple POJO TreeItem that stores a String text and String destination required for each goLink, along with a List of children TreeItem objects to reflect the hierarchy. At runtime we'll construct this tree programmatically populating the hierarchy in any way we desire.

The POJO approach is very easy to understand and implement. However the problem with our POJO approach is the datatype doesn't match that required by the <af:tree>, namely oracle.adf.view.faces.model.TreeModel. How do we address this?

Creating an Adapter between our TreeItem and TreeModel

In the OO world they have the concept of the adapter design pattern. An Adapter class is one that wraps another interface, to provide an interface the client expects. In our case we have our POJO TreeItem interface, but our client the <af:tree> demands an oracle.adf.view.faces.model.TreeModel, so we'll provide a class called TreeModelAdapter to work as the adapter. It will be this class that we'll define in our faces-config.xml file as a managed bean for the <af:tree> control to make use of at runtime.

The TreeModelAdapter will internally store our TreeItem hierarchy and TreeModel, and provide accessor methods to access and manipulate these items.

Coding the solution

The following describes the steps in coding our design solution. It assumes you've already created your web page with the <af:tree> code as previous:

Create our POJO Java Bean TreeItem class as follows:

package view;

import java.util.List;

public class TreeItem {
  private String _text = null;
  private String _destination = null;
  private List<treeitem> _children = null;

  public TreeItem(String text, String destination) {
    setText(text);
    setDestination(destination);
  }

  public String getText() { return _text; }
  public void setText(String text) { this._text = text; }

  public String getDestination() { return _destination; }
  public void setDestination(String destination) { this._destination = destination; }

  public List getChildren() { return _children; }
  public void setChildren(List children) { this._children = children; }
}

Note the following about the TreeItem class:

  • Internally stores the Strings text and destination and provides appropriate accessors.
  • Contains a list of child TreeItems _children that may contain 0, 1 or many child TreeItem objects within the current TreeItem. This represents the hierarchy. Note that it is important the Java Bean provides accessors specifically named getChildren() and setChildren() to retrieve the private _children attribute as you'll see in a moment.
Create a TreeModelAdapter class:

package view;

import java.beans.IntrospectionException;
import java.util.ArrayList;
import java.util.List;
import oracle.adf.view.faces.model.ChildPropertyTreeModel;
import oracle.adf.view.faces.model.TreeModel;

public class TreeModelAdapter {
  private Object _instance = null;
  private transient TreeModel _model = null;

  public TreeModelAdapter() {

    ArrayList<TreeItem> rootTreeItems = new ArrayList<TreeItem>();

    TreeItem treeItem1 = new TreeItem("Fish", "http://www.someurl1.com");
    TreeItem treeItem2 = new TreeItem("Dog", "http://www.someurl2.com");
    TreeItem treeItem3 = new TreeItem("Cat", "http://www.someurl3.com");

    TreeItem treeItem2_1 = new TreeItem("Blue Heeler", "http://www.someurl4.com");

    TreeItem treeItem2_1_1 = new TreeItem("Rover", "http://www.someurl5.com");
    TreeItem treeItem2_1_2 = new TreeItem("Ruffus", "http://www.someurl6.com");

    rootTreeItems.add(treeItem1);
    rootTreeItems.add(treeItem2);
    rootTreeItems.add(treeItem3);

    ArrayList<TreeItem> treeItem2Children = new ArrayList<TreeItem>();
    ArrayList<TreeItem> treeItem2_1Children = new ArrayList<TreeItem>();

    treeItem2Children.add(treeItem2_1);
    treeItem2.setChildren(treeItem2Children);

    treeItem2_1Children.add(treeItem2_1_1);
    treeItem2_1Children.add(treeItem2_1_2);
    treeItem2_1.setChildren(treeItem2_1Children);

    this.setListInstance(rootTreeItems);
  }

  public TreeModel getModel() throws IntrospectionException {
    if (_model == null) {
      _model = new ChildPropertyTreeModel(_instance, "children");
    }
    return _model;
  }

  public void setListInstance(List instance) {
    _instance = instance;
    _model = null;
  }
}


Note the following about the TreeModelAdapter class:
  • It contains a private oracle.adf.view.faces.model.TreeModel _model attribute. This is the TreeModel we'll provide to the <af:tree> tag. It is exposed via the getModel() method, and you previously saw this method was called via the <af:tree value="#{treeModel.model"> EL expression.
  • The class also contains an Object named _instance. This is where we'll store our own programmatic tree constructed from our own home baked Java Bean TreeItem hierarchy. The nice thing about this implementation is it doesn't care if it gets our TreeItem class, or any other sort of Java Bean, as long as it follows the Java Bean spec by providing accessors to retrieve the attributes, including specifically accessors for _children (more on this soon). The setListInstance() accessor provides a method to set the Object _instance.
  • In our simple example here, the constructor creates 3 root TreeItem nodes "Fish", "Dog", "Cat". For the "Dog" TreeItem node it creates a child "Blue Heeler" node. For the "Blue Heeler" node it creates 2 TreeItem nodes "Rover" and "Ruffus" in turn. The constructors last action is to assign the TreeItem hierarchy we've populated into rootTreeItems into the TreeModelAdapter class's _instance private attribute.
  • The getModel() method requires further explanation. The ChildPropertyTreeModel class is a subclass of oracle.adf.view.faces.model.TreeModel. It allows the construction of a TreeModel based on a list of beans. This suites our purposes well as we've constructed a list of TreeItem beans stored in the TreeModelAdapter's _instance attribute. You'll note that the ChildPropertyTreeModel constructor for its 2nd parameter specifies the String "children". The ChildPropertyTreeModel class uses this name to work out what accessor methods it needs to use in the TreeItem Java Bean to access the hierarchical part of the TreeItem class. It's important that the string "children" matches the accessor names getChildren() and setChildren() in the TreeItem class following the Java Bean specification rules. If these mismatch you'll get a runtime error.
Finally in our faces-config.xml file we declare our managed bean as follows:

<managed-bean>
  <managed-bean-name>treeModel
  <managed-bean-class>view.TreeModelAdapter
  <managed-bean-scope>request
</managed-bean>

Note that the request scope used for treeModel will result in the instantiation of TreeModelAdapter for each request to the page containing the treeModel reference, potentially an expensive exercise. If the tree is duplicated across multiple screens a session scope may be appropriate.

Credit

To give credit the inspiration for the TreeModelAdapter in this solution is a modification of MenuTreeModelAdapter from Oracle's ADF Developer's Guide for Forms/4GL Developers 10.1.3 (page 19-8). Those with lateral thinking should be able to see the ability to create programmatic <af:page> and <af:panelPage> menus with this technique.

Final Caveat

The code above is not applicable for JDev 11g and its new Rich Faces components as the class structure for the components has changed. Once Oracle releases the JavaDocs for the components I'll look at revising this article on request. 

 

分享到:
评论

相关推荐

    pyqt treemodel使用checkbox例子代码

    pyqt treemodel使用checkbox例子代码

    Qt:在TreeModel+QTreeView中使用复选框(checkbox)

    QTreeView Checkboxes 需要实现一个功能:在QT的TreeView中,能够使用复选框,并且选中父节点的复选框可以全选或取消子节点的复选框。 参考链接: http://blog.csdn.net/ajaxhe/article/details/7518285

    Java FileSystem TreeModel-开源

    FileSystem TreeModel for Java 项目旨在提供一个简单易学的 TreeModel API,它允许 TreeModel 查看器显示文件系统而无需编写任何代码。

    实现Qtreeview 重写model 实现model中添加按钮的功能

    通过qtreeview 重写treemodel 实现树节点不同的特性,然后操作item的delegate绘制控件。

    tree model

    这段只能实现播放功能 我想要暂停和关闭功能 怎么做到?

    EXT 树形结构样例

    EXT 树形结构样例:用JSON格式返回数据类型

    SATree:SQLAlchemy的TreeModel

    树的一个节点在存储为一条记录,表现为SQLALchemy一个混合了TreeMixin的Model实例。安装通过pip进行安装pip install satree直接下载源代码,导入就可以使用from satree imoport TreeMixin,TreeManager快速使用SAtree...

    QTreeView树形视图使用自定义模型model

    QTreeView树形视图使用自定义模型model,不是改造QT例子。

    c#windowform实现treeview多层绑定

    实现treeview多层数据绑定,多层是动态的

    QTreeView+自定义Model实现示例

    QTreeView是用来显示树型结构的数据,比如目录组织,公司组织架构等,数据量小可以用Qt自带的Model实现,如果数据量大,则需要用自定义的Model实现,下面介绍自定义实现的方法。

    TreeViewModel_new.zip

    自定义TreeModel,并且能够在数据刷新后维持Treeview的展开状态

    QTreeView实现节点拖动.zip

    此例子通过自定义Treemodel和treeitem实现了Qtreeview的节点可以拖动到另一节点下,可以用来实现数据分组等操作。

    QTreeModel的使用(例程)

    可编辑的QTreeModel的使用例程,由于TreeModel比较难理解,建议在例程的基础上修改使用

    QJsonModel:Qt Json树模型

    QJson模型QJsonModel是基于QAbstractItemModel的Qt5 / C ++ 11 / Python的json树模型类。 QJsonModel已获得MIT许可。用法C ++ 将qjsonmodel.cpp和qjsonmodel.h添加到您的项目中。 QJsonModel * model = new ...

    java界面程序代码

    sql=sql + "and classid in(select id from classclass where rtrim(ltrim(str(id)))like(select ltrim(rtrim(str(id)))+'%'from classclass where rtrim(ltrim(name))='"+name+"'))"; try{ rs = stmt....

    jtable增删改查和jtree连接

    String[] b2=new String[]{"2","cc","546","fgh","23.5","9787561748008"}; String[] b3=new String[]{"3","dd","678","bnm","23.5","9787561748008"}; v.add(b0); v.add(b1); v.add(b2); v.add(b3); ...

    treesnip:防风草后端为“ tree”,“ lightGBM”和“ Catboost”

    remotes :: install_github( " curso-r/treesnip " )最小的例子# decision_treemodel &lt;- parsnip :: decision_tree()parsnip :: set_engine( model , " tree " )# boost_treemodel &lt;- parsnip :: boost_tree...

    JAVA写的读取ini文件

    里面用到了树。表格,以及右键,另存为等,还有树和表格编辑器的编写,并且实现了TreeModel接口,附ini文件,请先执行,“文件--打开”操作

    swing界面设计之JTree

    (十九) 向 Java 应用程序伸出援助之手——用 JavaHelp 2.0 构建下一个 Java 应用程序的帮助系统 115 入门 116 使用 HelpSet 117 HelpSet 数据文件 118 helpset 文件 118 maps 部分 119 view 部分 119 presentation ...

Global site tag (gtag.js) - Google Analytics