KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > compiere > model > MTree


1 /******************************************************************************
2  * The contents of this file are subject to the Compiere License Version 1.1
3  * ("License"); You may not use this file except in compliance with the License
4  * You may obtain a copy of the License at http://www.compiere.org/license.html
5  * Software distributed under the License is distributed on an "AS IS" basis,
6  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
7  * the specific language governing rights and limitations under the License.
8  * The Original Code is Compiere ERP & CRM Business Solution
9  * The Initial Developer of the Original Code is Jorg Janke and ComPiere, Inc.
10  * Portions created by Jorg Janke are Copyright (C) 1999-2001 Jorg Janke, parts
11  * created by ComPiere are Copyright (C) ComPiere, Inc.; All Rights Reserved.
12  * Contributor(s): ______________________________________.
13  *****************************************************************************/

14 package org.compiere.model;
15
16 import java.sql.*;
17 import java.util.*;
18 import javax.sql.*;
19
20 import org.compiere.util.*;
21
22 /**
23  * Builds Tree.
24  * Creates tree structure - maintained in VTreePanel
25  *
26  * @author Jorg Janke
27  * @version $Id: MTree.java,v 1.6 2003/11/06 07:08:06 jjanke Exp $
28  */

29 public class MTree extends X_AD_Tree
30 {
31     /**
32      * Construct Tree
33      * @param AD_Tree_ID The tree to build
34      * @param editable True, if tree can be modified
35      * - includes inactive and empty summary nodes
36      * @param ctx context for security
37      */

38     public MTree (Properties ctx, int AD_Tree_ID, boolean editable)
39     {
40         super(ctx, AD_Tree_ID);
41         log.info("AD_Tree_ID=" + AD_Tree_ID + ", Editable=" + editable);
42         m_editable = editable;
43
44         int AD_User_ID = Env.getContextAsInt(ctx, "AD_User_ID");
45         loadNodes(AD_User_ID);
46     } // MTree
47

48     /** Is Tree editable */
49     private boolean m_editable;
50     /** Table Name */
51     private String JavaDoc m_nodeTableName = "AD_TreeNode";
52     /** Root Node */
53     private MTreeNode m_root = null;
54     /** Buffer while loading tree */
55     private ArrayList m_buffer = new ArrayList();
56     /** Prepared Statement for Node Details */
57     private RowSet m_nodeRowSet;
58
59     /*************************************************************************/
60
61     /**
62      * Get primary AD_Tree_ID for KeyColumn.
63      * Called from GridController
64      * @param keyColumnName key column name, eg. C_Project_ID
65      * @return AD_Tree_ID
66      */

67     public static int getAD_Tree_ID (String JavaDoc keyColumnName)
68     {
69         Log.trace(Log.l4_Data, "MTree.getAD_Tree_ID", keyColumnName);
70         if (keyColumnName == null || keyColumnName.length() == 0)
71             return 0;
72
73         String JavaDoc TreeType = null;
74         if (keyColumnName.equals("AD_Menu_ID"))
75             TreeType = TREETYPE_Menu;
76         else if (keyColumnName.equals("C_ElementValue_ID"))
77             TreeType = TREETYPE_ElementValueAccountEtc;
78         else if (keyColumnName.equals("M_Product_ID"))
79             TreeType = TREETYPE_Product;
80         else if (keyColumnName.equals("C_BPartner_ID"))
81             TreeType = TREETYPE_BusPartner;
82         else if (keyColumnName.equals("AD_Org_ID"))
83             TreeType = TREETYPE_Organization;
84         else if (keyColumnName.equals("C_Project_ID"))
85             TreeType = TREETYPE_Project;
86         else if (keyColumnName.equals("M_ProductCategory_ID"))
87             TreeType = TREETYPE_ProductCategory;
88         else if (keyColumnName.equals("M_BOM_ID"))
89             TreeType = TREETYPE_BoM;
90         else if (keyColumnName.equals("C_SalesRegion_ID"))
91             TreeType = TREETYPE_SalesRegion;
92         else if (keyColumnName.equals("C_Campaign_ID"))
93             TreeType = TREETYPE_Campaign;
94         else if (keyColumnName.equals("C_Activity_ID"))
95             TreeType = TREETYPE_Activity;
96         else
97         {
98             Log.error("MTree.getAD_Tree_ID - Could not map " + keyColumnName);
99             return 0;
100         }
101
102         int AD_Tree_ID = 0;
103         int AD_Client_ID = Env.getContextAsInt(Env.getCtx(), "#AD_Client_ID");
104         String JavaDoc sql = "SELECT AD_Tree_ID,Name FROM AD_Tree "
105             + "WHERE AD_Client_ID=? AND TreeType=? AND IsActive='Y'";
106         try
107         {
108             PreparedStatement pstmt = DB.prepareStatement(sql);
109             pstmt.setInt(1, AD_Client_ID);
110             pstmt.setString(2, TreeType);
111             ResultSet rs = pstmt.executeQuery();
112             if (rs.next())
113                 AD_Tree_ID = rs.getInt(1);
114             rs.close();
115             pstmt.close();
116         }
117         catch (SQLException e)
118         {
119             Log.error("MTree.getAD_Tree_ID", e);
120         }
121
122         return AD_Tree_ID;
123     } // getAD_Tree_ID
124

125
126     /**
127      * Get Primary Tree of Tree Type
128      * @param TreeType see TREETYPE_
129      * @param ctx context for Security
130      * @return MTree
131      */

132     public static MTree getTree (Properties ctx, String JavaDoc TreeType)
133     {
134         int AD_Tree_ID = 0;
135         int AD_Client_ID = Env.getContextAsInt(Env.getCtx(), "#AD_Client_ID");
136         String JavaDoc sql = "SELECT AD_Tree_ID,Name FROM AD_Tree "
137             + "WHERE AD_Client_ID=? AND TreeType=? AND IsActive='Y'";
138         try
139         {
140             PreparedStatement pstmt = DB.prepareStatement(sql);
141             pstmt.setInt(1, AD_Client_ID);
142             pstmt.setString(2, TreeType);
143             ResultSet rs = pstmt.executeQuery();
144             if (rs.next())
145                 AD_Tree_ID = rs.getInt(1);
146             rs.close();
147             pstmt.close();
148         }
149         catch (SQLException e)
150         {
151             Log.error("MTree.getTree", e);
152         }
153         // Not found
154
if (AD_Tree_ID == 0)
155         {
156             Log.trace(Log.l4_Data, "MTree.getTree - No AD_Tree_ID for TreeType=" + TreeType + ", AD_Client_ID=" + AD_Client_ID);
157             return null;
158         }
159         //
160
MTree tree = new MTree (ctx, AD_Tree_ID, false);
161         return tree;
162     } // getTree
163

164
165     /*************************************************************************
166
167     /**
168      * Load Nodes and Bar
169      * @param AD_User_ID user
170      */

171     private void loadNodes (int AD_User_ID)
172     {
173         // TableName: AD_TreeNode
174
if (getTreeType().equals(TREETYPE_Menu))
175             ; // m_tableName += "MM";
176
else if (getTreeType().equals(TREETYPE_BusPartner))
177             m_nodeTableName += "BP";
178         else if (getTreeType().equals(TREETYPE_Product))
179             m_nodeTableName += "PR";
180
181         // SQL for TreeNodes
182
StringBuffer JavaDoc cmd = new StringBuffer JavaDoc("SELECT "
183             + "tn.Node_ID,tn.Parent_ID,tn.SeqNo,tb.IsActive "
184             + "FROM ").append(m_nodeTableName).append(" tn"
185             + " LEFT OUTER JOIN AD_TreeBar tb ON (tn.AD_Tree_ID=tb.AD_Tree_ID"
186             + " AND tn.Node_ID=tb.Node_ID AND tb.AD_User_ID=?) " // #1
187
+ "WHERE tn.AD_Tree_ID=?"); // #2
188
if (!m_editable)
189             cmd.append(" AND tn.IsActive='Y'");
190         cmd.append(" ORDER BY COALESCE(tn.Parent_ID, -1), tn.SeqNo");
191         Log.trace(Log.l6_Database, "MTree.loadNodes", cmd.toString());
192
193         // The Node Loop
194
try
195         {
196             // load Node details - addToTree -> getNodeDetail
197
getNodeDetails();
198             //
199
PreparedStatement pstmt = DB.prepareStatement(cmd.toString());
200             pstmt.setInt(1, AD_User_ID);
201             pstmt.setInt(2, getAD_Tree_ID());
202             // Get Tree & Bar
203
ResultSet rs = pstmt.executeQuery();
204             while (rs.next())
205             {
206                 int node_ID = rs.getInt(1);
207                 int parent_ID = rs.getInt(2);
208                 int seqNo = rs.getInt(3);
209                 boolean onBar = (rs.getString(4) != null);
210                 //
211
if (node_ID == 0 && parent_ID == 0)
212                     m_root = new MTreeNode (node_ID, 0, getName(), getDescription(), 0, true, null, onBar);
213                 else
214                     addToTree (node_ID, parent_ID, seqNo, onBar); // calls getNodeDetail
215
}
216             rs.close();
217             pstmt.close();
218             //
219
m_nodeRowSet.close();
220             m_nodeRowSet = null;
221         }
222         catch (SQLException e)
223         {
224             Log.error("MTree.loadNodes", e);
225             m_nodeRowSet = null;
226         }
227         
228         // Done with loading - add remainder from buffer
229
if (m_buffer.size() != 0)
230         {
231             Log.trace(Log.l6_Database, "MTree.loadNodes - clearing buffer");
232             for (int i = 0; i < m_buffer.size(); i++)
233             {
234                 MTreeNode node = (MTreeNode)m_buffer.get(i);
235                 MTreeNode parent = m_root.findNode(node.getParent_ID());
236                 if (parent != null && parent.getAllowsChildren())
237                 {
238                     parent.add(node);
239                     checkBuffer(node);
240                     m_buffer.remove(i);
241                     i = -1;
242                 }
243             }
244         }
245
246         // Nodes w/o parent
247
if (m_buffer.size() != 0)
248         {
249             Log.error ("MTree.loadNodes - Nodes w/o parent - adding to root - " + m_buffer);
250             for (int i = 0; i < m_buffer.size(); i++)
251             {
252                 MTreeNode node = (MTreeNode)m_buffer.get(i);
253                 m_root.add(node);
254                 checkBuffer(node);
255                 m_buffer.remove(i);
256                 i = -1;
257             }
258             if (m_buffer.size() != 0)
259                 Log.error ("MTree.loadNodes - still nodes in Buffer - " + m_buffer);
260         } // nodes w/o parents
261

262         // clean up
263
if (!m_editable && m_root.getChildCount() > 0)
264             trimTree();
265 // diagPrintTree();
266
} // loadNodes
267

268     /**
269      * Add Node to Tree.
270      * If not found add to buffer
271      * @param node_ID Node_ID
272      * @param parent_ID Parent_ID
273      * @param seqNo SeqNo
274      * @param onBar on bar
275      */

276     private void addToTree (int node_ID, int parent_ID, int seqNo, boolean onBar)
277     {
278         // Create new Node
279
MTreeNode child = getNodeDetail (node_ID, parent_ID, seqNo, onBar);
280         if (child == null)
281             return;
282
283         // Add to Tree
284
MTreeNode parent = null;
285         if (m_root != null)
286             parent = m_root.findNode (parent_ID);
287         // Parent found
288
if (parent != null && parent.getAllowsChildren())
289         {
290             parent.add(child);
291             // see if we can add nodes from buffer
292
if (m_buffer.size() > 0)
293                 checkBuffer(child);
294         }
295         else
296             m_buffer.add(child);
297     } // addToTree
298

299     /**
300      * Check the buffer for nodes which have newNode as Parents
301      * @param newNode new node
302      */

303     private void checkBuffer (MTreeNode newNode)
304     {
305         for (int i = 0; i < m_buffer.size(); i++)
306         {
307             MTreeNode node = (MTreeNode)m_buffer.get(i);
308             if (node.getParent_ID() == newNode.getID())
309             {
310                 newNode.add(node);
311                 m_buffer.remove(i);
312                 i--;
313             }
314         }
315     } // checkBuffer
316

317     /*************************************************************************/
318
319     /**
320      * Get Node Detail.
321      * Loads data into RowSet m_nodeRowSet
322      * Columns:
323      * - ID
324      * - Name
325      * - Description
326      * - IsSummary
327      * - ImageIndicator
328      * - additional for Menu
329      * Parameter:
330      * - Node_ID
331      * The SQL contains security/access control
332      * @return SQL to get Node Detail Info
333      */

334     private void getNodeDetails ()
335     {
336         // SQL for Node Info
337
StringBuffer JavaDoc sqlNode = new StringBuffer JavaDoc();
338         String JavaDoc sourceTable = null;
339         if (getTreeType().equals(TREETYPE_Menu))
340         {
341             boolean base = Env.isBaseLanguage(Env.getCtx(), "AD_Menu");
342             sourceTable = "m";
343             if (base)
344                 sqlNode.append("SELECT m.AD_Menu_ID, m.Name,m.Description,m.IsSummary,m.Action, "
345                     + "m.AD_Window_ID, m.AD_Process_ID, m.AD_Form_ID, m.AD_Workflow_ID, m.AD_Task_ID, m.AD_Workbench_ID "
346                     + "FROM AD_Menu m");
347             else
348                 sqlNode.append("SELECT m_AD_Menu_ID, t.Name,t.Description,m.IsSummary,m.Action, "
349                     + "m.AD_Window_ID, m.AD_Process_ID, m.AD_Form_ID, m.AD_Workflow_ID, m.AD_Task_ID, m.AD_Workbench_ID "
350                     + "FROM AD_Menu m, AD_Menu_Trl t");
351             if (!base)
352                 sqlNode.append(" WHERE m.AD_Menu_ID=t.AD_Menu_ID AND t.AD_Language='")
353                     .append(Env.getAD_Language(Env.getCtx())).append("'");
354             if (!m_editable)
355             {
356                 boolean hasWhere = sqlNode.indexOf(" WHERE ") != -1;
357                 sqlNode.append(hasWhere ? " AND " : " WHERE ").append(" m.IsActive='Y' ");
358             }
359         }
360         else
361         {
362             if (getTreeType().equals(TREETYPE_Organization))
363                 sourceTable = "AD_Org";
364             else if (getTreeType().equals(TREETYPE_Product))
365                 sourceTable = "M_Product";
366             else if (getTreeType().equals(TREETYPE_ProductCategory))
367                 sourceTable = "M_Product_Category";
368             else if (getTreeType().equals(TREETYPE_BoM))
369                 sourceTable = "M_BOM";
370             else if (getTreeType().equals(TREETYPE_ElementValueAccountEtc))
371                 sourceTable = "C_ElementValue";
372             else if (getTreeType().equals(TREETYPE_BusPartner))
373                 sourceTable = "C_BPartner";
374             else if (getTreeType().equals(TREETYPE_Campaign))
375                 sourceTable = "C_Campaign";
376             else if (getTreeType().equals(TREETYPE_Project))
377                 sourceTable = "C_Project";
378             else if (getTreeType().equals(TREETYPE_Activity))
379                 sourceTable = "C_Activity";
380             else if (getTreeType().equals(TREETYPE_SalesRegion))
381                 sourceTable = "C_SalesRegion";
382             if (sourceTable == null)
383             {
384                 throw new IllegalArgumentException JavaDoc("MTree.prepareNodeDetail - Unknown TreeType=" + getTreeType());
385             }
386             sqlNode.append("SELECT ").append(sourceTable).append("_ID,Name,Description,IsSummary,NULL FROM ")
387                 .append(sourceTable);
388             if (!m_editable)
389                 sqlNode.append(" WHERE IsActive='Y'");
390         }
391         String JavaDoc sql = MRole.getDefault(getCtx(), false).addAccessSQL(sqlNode.toString(),
392             sourceTable, MRole.SQL_FULLYQUALIFIED, m_editable);
393         log.debug("getNodeDetails - " + sql);
394         m_nodeRowSet = DB.getRowSet (sql);
395     } // getNodeDetails
396

397     /**
398      * Get Node Details.
399      * As SQL contains security access, not all nodes will be found
400      * @param node_ID Key of the record
401      * @param parent_ID Parent ID of the record
402      * @param seqNo Sort index
403      * @param onBar Node also on Shortcut bar
404      * @return Node
405      */

406     private MTreeNode getNodeDetail (int node_ID, int parent_ID, int seqNo, boolean onBar)
407     {
408         MTreeNode retValue = null;
409         try
410         {
411             m_nodeRowSet.beforeFirst();
412             while (m_nodeRowSet.next())
413             {
414                 int node = m_nodeRowSet.getInt(1);
415                 if (node_ID != node) // search for correct one
416
continue;
417                 //
418
int index = 2;
419                 String JavaDoc name = m_nodeRowSet.getString(index++);
420                 String JavaDoc description = m_nodeRowSet.getString(index++);
421                 boolean isSummary = "Y".equals(m_nodeRowSet.getString(index++));
422                 String JavaDoc action = m_nodeRowSet.getString(index++);
423                 //
424
if (getTreeType().equals(TREETYPE_Menu) && !isSummary)
425                 {
426                     int AD_Window_ID = m_nodeRowSet.getInt(index++);
427                     int AD_Process_ID = m_nodeRowSet.getInt(index++);
428                     int AD_Form_ID = m_nodeRowSet.getInt(index++);
429                     int AD_Workflow_ID = m_nodeRowSet.getInt(index++);
430                     int AD_Task_ID = m_nodeRowSet.getInt(index++);
431                     int AD_Workbench_ID = m_nodeRowSet.getInt(index++);
432                     //
433
MRole role = MRole.getDefault(getCtx(), false);
434                     Boolean JavaDoc access = null;
435                     if (X_AD_Menu.ACTION_Window.equals(action))
436                         access = role.getWindowAccess(AD_Window_ID);
437                     else if (X_AD_Menu.ACTION_Process.equals(action) || X_AD_Menu.ACTION_Report.equals(action))
438                         access = role.getProcessAccess(AD_Process_ID);
439                     else if (X_AD_Menu.ACTION_Form.equals(action))
440                         access = role.getFormAccess(AD_Form_ID);
441                     else if (X_AD_Menu.ACTION_WorkFlow.equals(action))
442                         access = role.getWorkflowAccess(AD_Workflow_ID);
443                     else if (X_AD_Menu.ACTION_Task.equals(action))
444                         access = role.getTaskAccess(AD_Task_ID);
445                 // else if (X_AD_Menu.ACTION_Workbench.equals(action))
446
// access = role.getWorkbenchAccess(AD_Window_ID);
447
// log.debug("getNodeDetail - " + name + " - " + action + " - " + access);
448
//
449
if (access != null) // rw or ro
450
{
451                         retValue = new MTreeNode (node_ID, seqNo,
452                             name, description, parent_ID, isSummary,
453                             action, onBar);
454                     }
455                 }
456                 else
457                 { // always add
458
retValue = new MTreeNode (node_ID, seqNo,
459                         name, description, parent_ID, isSummary,
460                         action, onBar);
461                 }
462             }
463         }
464         catch (SQLException e)
465         {
466             log.error("getNodeDetails", e);
467         }
468         return retValue;
469     } // getNodeDetails
470

471     /*************************************************************************/
472
473     /**
474      * Trim tree of empty summary nodes
475      */

476     private void trimTree()
477     {
478         boolean needsTrim = m_root != null;
479         while (needsTrim)
480         {
481             needsTrim = false;
482             Enumeration en = m_root.preorderEnumeration();
483             while (en.hasMoreElements())
484             {
485                 MTreeNode nd = (MTreeNode)en.nextElement();
486                 if (nd.isSummary() && nd.getChildCount() == 0)
487                 {
488                     nd.removeFromParent();
489                     needsTrim = true;
490                 }
491             }
492         }
493     } // trimTree
494

495     /**
496      * Diagnostics: Print tree
497      */

498     private void diagPrintTree()
499     {
500         Enumeration en = m_root.preorderEnumeration();
501         int count = 0;
502         while (en.hasMoreElements())
503         {
504             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
505             MTreeNode nd = (MTreeNode)en.nextElement();
506             for (int i = 0; i < nd.getLevel(); i++)
507                 sb.append(" ");
508             sb.append("ID=").append(nd.getID())
509                 .append(", SeqNo=").append(nd.getSeqNo())
510                 .append(" ").append(nd.getName());
511             System.out.println(sb.toString());
512             count++;
513         }
514         System.out.println("Count=" + count);
515     } // diagPrintTree
516

517     /**
518      * Get Root node
519      * @return root
520      */

521     public MTreeNode getRoot()
522     {
523         return m_root;
524     } // getRoot
525

526     /**
527      * Get Node Table Name
528      * @return Table Name
529      */

530     public String JavaDoc getNodeTableName()
531     {
532         return m_nodeTableName;
533     } // getTableName
534

535     /**
536      * String representation
537      * @return info
538      */

539     public String JavaDoc toString()
540     {
541         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("MTree[");
542         sb.append("AD_Tree_ID=").append(getAD_Tree_ID())
543             .append(", Name=").append(getName());
544         sb.append("]");
545         return sb.toString();
546     }
547 } // MTree
548
Popular Tags