0

TreeModel How to?

asked 2011-01-21 01:13:42 +0800

drishtisv gravatar image drishtisv
135 2

updated 2011-01-21 04:51:08 +0800

Dear All,

I require a Tree List in a following fashion which has been filled by a Database Table. and also require manipulation effects to Tree List (I tried it in many way but I am not able to do)

-ASSET (Group)
    -Fixed Asset (Group)
         +Furniture (Group)
          - Electronics Machineries (Group)
                - Computers & Printers (Group)
                       - Dell Server (Item)
                       - HP Notebook (Item)
                + UPS Systems (Group)
    + Current Assets(Group)
+ Liablities(Group)
+ Income(Group)
+ Expenditure(Group)

User can add and remove the groups as well as Items

Thanks in advance

delete flag offensive retag edit

11 Replies

Sort by » oldest newest

answered 2011-01-23 22:07:02 +0800

drishtisv gravatar image drishtisv
135 2

Hi all experts,

anybody have any solution or please give me some hits

link publish delete flag offensive edit

answered 2011-01-24 02:14:56 +0800

samchuang gravatar image samchuang
4084 4

Hi
you can refer to Tree Model

link publish delete flag offensive edit

answered 2011-01-24 06:24:38 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

updated 2011-01-24 06:27:04 +0800

In this threads is all what you need. But it should be optimized because it have too much DB calls.

The magic is the right table structure.
- Each ChildNode have a field 'parentNode' wich holds the record ID of it's parent.
- In your case you must extend it to a flag field 'Group' (boolean) = true/false and handle this flag in the ItemRenderer.


In my case the structure (simplified) for a tree that depends on a master entry looks like:

MasterTable
/* EN: Create the NAMES of the several charts of accounts for the tenants */
/* DE: Erzeuge Kontenrahmen Bezeichnung fuer die Test-Mandanten */
INSERT INTO fib_kto_rahmen ( ktr_id,
                             ktr_tnt_id,
                             ktr_shorttext,
                             ktr_longtext ) values
(   1,  10, 'DATEV SKR03', 'Standardkontenrahmen 03 fuer Personengesellschaften'),
(   2,  10, 'DATEV SKR04', 'Standardkontenrahmen 04 fuer Kapitalgesellschaften');

DETAIL Tree records
/* EN: Create the names of the several account categories for charts of accounts */
/*     here for: 'KontoRahmen SKR03' for test tenant-ID='10' */
/* DE: Erzeuge Konten-Kategorien fuer die Kontenrahmen der Test-Mandanten */
/*     hier fuer 'KontoRahmen SKR03' fuer Test Mandant ID='10' */
INSERT INTO fib_kto_kategorie ( kkg_id,
                                kkg_tnt_id,
                                kkg_ktr_id,
                                kkg_shorttext,
                                kkg_parent_node ) values
/* Debitoren */
(   1,  10,  1, 'SKR03 Kontorahmen',                   0 ),
(   5,  10,  1, 'Debitoren',                                    1  ),
(   6,  10,  1, 'sonstige',                                      5 ),
/* Kreditoren */
(  10,  10,  1, 'Kreditoren',                                  1 ),
(  11,  10,  1, 'sonstige',                                   10 ),
/* Sachkonten */
(  20,  10,  1, 'Sachkonten',                                1 ),
/* Abschreibungen */
(  30,  10,  1, 'Abschreibungen',                          20 ),
(  31,  10,  1, 'Finanzanlagen',                            30 ),
(  32,  10,  1, 'Geringwertige WG',                       30 ),
(  33,  10,  1, 'Sachanlagen',                                30 ),
(  34,  10,  1, 'sonstige',                                      30 ),
/* Aktive Rechnungsabgrenzung */  
(  40,  10,  1, 'Aktive Rechnungsabgrenzung',     20 ),
(  41,  10,  1, 'sonstige',                                      40 ),
/* Anlagevermoegen */ 
(  50,  10,  1, 'Anlagevermögen',                         20 ),
(  51,  10,  1, 'Finanzanlagen',                            50 ),
(  52,  10,  1, 'Firmenwert',                                  50 ),
(  53,  10,  1, 'Geringwertige WG',                       50 ),
(  54,  10,  1, 'Sachanlagen',                               50 ),
(  55,  10,  1, 'sonstige',                                      50 ),
/* Betriebsausgaben */
(  60,  10,  1, 'Betriebsausgaben',                       20 ),
(  61,  10,  1, 'betriebliche Steuern',                    60 ),
(  62,  10,  1, 'Bewirtungskosten',                        60 );
. . .

Looks like


/* RootNode */
SKR03 Kontorahmen
  - Debitoren
     - sonstige
  - Kreditoren
       - sonstige
   - ( ID=20) Sachkonten
        - (ID=30) Abschreibungen (parentNode=20)
            - Finanzanlagen (parentNode=30)
            - Geringwertige WG (parentNode=30)
            - Sachanlagen (parentNode=30)
    . . .

Hope it helps a little bit. Here is a pic of the running tree.

best
Stephan

link publish delete flag offensive edit

answered 2011-01-24 07:15:37 +0800

drishtisv gravatar image drishtisv
135 2

Hi samchuang,

I read Tree Model but I confused how to make it with database table. Is any example for reference?

link publish delete flag offensive edit

answered 2011-01-24 07:39:07 +0800

drishtisv gravatar image drishtisv
135 2

HI terrytornado,

Thanks I have read this article. I have to show records of a table in a tree fashion. shown above.

link publish delete flag offensive edit

answered 2011-01-24 18:46:12 +0800

samchuang gravatar image samchuang
4084 4

Hi

first, you can try hard code to build a tree, after you success. You can read record from database and build the tree by record

link publish delete flag offensive edit

answered 2011-01-25 00:54:53 +0800

drishtisv gravatar image drishtisv
135 2

updated 2011-01-25 00:55:43 +0800

Hi samchuang,

I am confused how to fill ModelTree with Parent & Child relationship. Following is the snapshot of Table Data.

acno     acgroupflag    parentgrp      acname    
1          G                   0                   ASSET
2          G                   1                   Fixed Asset
3          G                   2                   Furniture (Group)
4          G                   3                   Electronics Machineries
5          G                   4                   Computers & Printers
6          I                    5                   Dell Server (Item)
7          I                    5                   HP Notebook (Item)
8          G                   4                   UPS Systems (Group)
9          G                   1                   Current Assets(Group)
10        G                   0                   Liablities(Group)
11        G                   0                   Income(Group)
12        G                   0                   Expenditure(Group)

Thanks

link publish delete flag offensive edit

answered 2011-01-25 06:19:27 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

updated 2011-01-25 06:27:24 +0800

again, there's all in Rico's thread with good explanations. You must adapt it to your needs (beans).

Here's my adaptions for a special need. And yes, that's a few classes. That's the reason why answering is difficult. It costs much time to prepare such things for demonstration.
So i can only give you the codes. In hope you take the time for studying.
So it's java, there is the way over objects. So we take objects to hold the DB's data. For a tree we need special classes that holds the data.

Remember: The tree is hierarchical ordered. So it's necessary to use ordered db data ( by PerantNodeID ) by a fit table select statement.

Tree
   --> TreeitemRenderer
             --> TreeModel
                     --> hold TreeItems
                              --> holds TreeNodes

.
call in the controller

	/**
	 * EN: Fill the accountCategories Tree with data depended on the defined
	 * chart of accounts.<br>
	 * DE: Fuellt den KontoKategorie Baum abhaengig vom gewaehlten KontoRahmen.<br>
	 */
	public void doFillKontoKategorieTree() {

		doFitSize();

		// Force to start filling the root's children
		if (getSelectedKontoRahmen() != null) {

			Tenant tenant = ((UserImpl) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUserTenant();

			// CREATE the ROOT Node
			RootKontoKategoryNode root = new RootKontoKategoryNode();
			root.setTenant(tenant);
			root.setKontoRahmen(getSelectedKontoRahmen());
			// START reading the Nodes
			root.readChildren();

			// CREATE and SET the model to tree
			FDTreeModel tm = new FDTreeModel(root);
			tree_KontoKategorie.setModel(tm);
			tree_KontoKategorie.setTreeitemRenderer(new KontoKategorieTreeItemRenderer());
		}
	}


     ONLY FOR SHOWING (this method is from an other Tree, sorry)

	/**
	 * Selects the object in the tree by a doubleClick.<br>
	 * Event is forwarded in the corresponding
	 * ItemRenderer(FibuReportCategoryTreeItemRenderer).
	 */
	public void onDoubleClickedFibuBerichtKategoryItem(Event event) {
		// logger.debug(event.toString());

		/**
		 * We CAST it down to the right component
		 */
		Treeitem ti = (Treeitem) ((ForwardEvent) event).getOrigin().getTarget();
		FibuBerichtKategorie fibuBerichtKategorie = ((FibuReportCategoryNode) ti.getAttribute("data")).getFibuBerichtKategorie();

		if (fibuBerichtKategorie != null) {
			setSelectedFibuBerichtKategorie(fibuBerichtKategorie);

                        . . .
		}
	}



TreeItemRenderer

/**
 * ItemRenderer for the Tree.<br>
 * First and second level have different icons.<br>
 * 
 * @author Stephan Gerth
 */
public class KontoKategorieTreeItemRenderer implements TreeitemRenderer {

	@Override
	public void render(Treeitem item, Object data) throws Exception {

		item.setAttribute("data", data);

		Treerow tr = new Treerow();
		tr.setParent(item);

		Treecell tc = new Treecell();

		// set the icon, depending of the level of the tree
		if (data instanceof RootKontoKategoryNode) {

			// Cast it down
			KontoKategorie kontoKategorie = ((RootKontoKategoryNode) data).getKontoKategorie();

			tc.setLabel(kontoKategorie.getShorttext());
			tc.setStyle("text-align: left");
			tc.setParent(tr);

			if (kontoKategorie.getParentNode() == 0) {
				tc.setImage("/images/icons/view.gif");
			} else if (kontoKategorie.getParentNode() != 0) {
				tc.setImage("/images/icons/index_16x16.gif");
			}

		} else if (data instanceof KontoKategoryNode) {
			KontoKategorie kontoKategorie = ((KontoKategoryNode) data).getKontoKategorie();

			tc.setLabel(kontoKategorie.getShorttext());
			tc.setStyle("text-align: left");
			tc.setParent(tr);

			if (kontoKategorie.getParentNode() == 0) {
				tc.setImage("/images/icons/view.gif");
			} else if (kontoKategorie.getParentNode() != 0) {
				tc.setImage("/images/icons/index_16x16.gif");
			}
		}

		item.setOpen(false);

		ComponentsCtrl.applyForward(item, "onDoubleClick=onDoubleClickedKontoKategorieItem");
	}
}

.

TreeModel

/**
 * TreeModel class.
 * 
 */
public class FDTreeModel extends AbstractTreeModel {

	private static final long serialVersionUID = 1L;

	FDTreeNode root;

	public FDTreeModel(FDTreeNode root) {
		super(root);

		this.root = root;
	}

	@Override
	public Object getChild(Object parent, int arg1) {
		return ((FDTreeNode) parent).getChild(arg1);
	}

	@Override
	public int getChildCount(Object parent) {
		return ((FDTreeNode) parent).getChildCount();
	}

	@Override
	public boolean isLeaf(Object node) {

		if (node == null) {
			return true;
		}

		return ((FDTreeNode) node).isLeaf();
	}
}

.
TreeNode
/**
 * The method <b>readChildren</b> is defined as <b>'abstract'</b> so it must be
 * coded in the SubClass that inherits from this class, because the codes are
 * different dependend of the used beans where we will bind in that SubClass.<br>
 * 
 */
public abstract class FDTreeNode {

	protected ArrayList<FDTreeNode> children = null;

	public abstract void readChildren();

	public ArrayList<FDTreeNode> getChildren() {
		return children;
	}

	public FDTreeNode getChild(int arg1) {

		FDTreeNode child = null;

		if (children == null) {
			readChildren();
		}

		if (children != null && (arg1 > -1) && (arg1 < children.size())) {
			child = children.get(arg1);
		}

		return child;
	}

	public int getChildCount() {

		if (children == null) {
			readChildren();
		}

		if (children != null) {
			return children.size();
		}

		return 0;
	}

	public boolean isLeaf() {

		return (getChildCount() == 0);
	}
}

.
RootNode
/**
 * Starter Class.
 * 
 * KontoKategory SubClass for the <b>ROOT</b> TreeNode. <br>
 * Here we coded the <b>abstract readChildren() method</b> of the ParentClass.
 * 
 * @author Stephan Gerth
 */
public class RootKontoKategoryNode extends FDTreeNode {

	// Services / DAO's / Beans
	private AccountingService accountingService;
	private Tenant tenant;
	private KontoKategorie kontoKategorie;
	private KontoRahmen kontoRahmen;

	@Override
	public void readChildren() {

		List<KontoKategorie> dbList = getAccountingService().getKontoKategoriesByParentNodeIdAndByKontoRahmen(getTenant().getId(), new Long(0), getKontoRahmen());

		if (dbList != null) {

			// System.out.println(dbList.size());

			children = new ArrayList<FDTreeNode>();

			for (int i = 0; i < dbList.size(); i++) {
				KontoKategoryNode k = new KontoKategoryNode();
				// we must set the Identifier for this child node
				k.setTenant(getTenant());
				k.setKontoRahmen(getKontoRahmen());
				k.setParentNodeId(dbList.get(i).getId());
				k.setKontoKategorie(dbList.get(i));

				children.add(k);
			}
		}

	}

	// +++++++++++++++++++++++++++++++++++++++++++++++++ //
	// ++++++++++++++++ Setter/Getter ++++++++++++++++++ //
	// +++++++++++++++++++++++++++++++++++++++++++++++++ //

	public void setKontoKategorie(KontoKategorie kontoKategorie) {
		this.kontoKategorie = kontoKategorie;
	}

	public KontoKategorie getKontoKategorie() {
		return kontoKategorie;
	}

	public void setAccountingService(AccountingService accountingService) {
		this.accountingService = accountingService;
	}

	public AccountingService getAccountingService() {
		if (accountingService == null) {
			accountingService = (AccountingService) SpringUtil.getBean("accountingService");
		}
		return accountingService;
	}

	public void setKontoRahmen(KontoRahmen kontoRahmen) {
		this.kontoRahmen = kontoRahmen;
	}

	public KontoRahmen getKontoRahmen() {
		return kontoRahmen;
	}

	public void setTenant(Tenant tenant) {
		this.tenant = tenant;
	}

	public Tenant getTenant() {
		return tenant;
	}

}

.
BeanNode
/**
 * KontoKategory SubClass for the TreeNodes. <br>
 * Here we coded the <b>abstract readChildren() method</b> of the ParentClass.
 * 
 * @author Stephan Gerth
 */
public class KontoKategoryNode extends FDTreeNode {

	// Services / DAO's / Beans
	private KontoKategorie kontoKategorie;
	private AccountingService accountingService;

	private long parentNodeId;
	private Tenant tenant;
	private KontoRahmen kontoRahmen;

	@Override
	public void readChildren() {

		// get the list of nodes from db
		List<KontoKategorie> dbList = getAccountingService().getKontoKategoriesByParentNodeIdAndByKontoRahmen(getTenant().getId(), getParentNodeId(), getKontoRahmen());

		if (dbList != null) {

			// System.out.println(dbList.size());

			children = new ArrayList<FDTreeNode>();

			for (int i = 0; i < dbList.size(); i++) {
				KontoKategoryNode k = new KontoKategoryNode();
				// we must set the Identifier for this child node
				k.setParentNodeId(dbList.get(i).getId());
				k.setKontoKategorie(dbList.get(i));
				k.setTenant(getTenant());
				k.setKontoRahmen(getKontoRahmen());

				children.add(k);
			}
		}

	}

	// +++++++++++++++++++++++++++++++++++++++++++++++++ //
	// ++++++++++++++++ Setter/Getter ++++++++++++++++++ //
	// +++++++++++++++++++++++++++++++++++++++++++++++++ //

	public void setKontoKategorie(KontoKategorie kontoKategorie) {
		this.kontoKategorie = kontoKategorie;
	}

	public KontoKategorie getKontoKategorie() {
		return kontoKategorie;
	}

	public void setAccountingService(AccountingService accountingService) {
		this.accountingService = accountingService;
	}

	public AccountingService getAccountingService() {
		if (accountingService == null) {
			accountingService = (AccountingService) SpringUtil.getBean("accountingService");
		}
		return accountingService;
	}

	public void setParentNodeId(long parentNodeId) {
		this.parentNodeId = parentNodeId;
	}

	public long getParentNodeId() {
		return parentNodeId;
	}

	public void setTenant(Tenant tenant) {
		this.tenant = tenant;
	}

	public Tenant getTenant() {
		return tenant;
	}

	public void setKontoRahmen(KontoRahmen kontoRahmen) {
		this.kontoRahmen = kontoRahmen;
	}

	public KontoRahmen getKontoRahmen() {
		return kontoRahmen;
	}

}

best
Stephan

link publish delete flag offensive edit

answered 2011-02-04 06:04:39 +0800

drishtisv gravatar image drishtisv
135 2

updated 2011-02-04 06:09:36 +0800

Thanks Stephan,

Sorry to say but still I am confused. Nothing any simple solution to bind an Array to treemodel? or when i click to tree item it display his nodes?

link publish delete flag offensive edit

answered 2011-02-04 08:03:43 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

updated 2011-02-04 08:05:00 +0800

A tree is one of the most complex things to handle :-(

You said you would get the logic from database...

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2011-01-21 01:13:42 +0800

Seen: 601 times

Last updated: Feb 05 '11

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More