package org.compiere.model;
import java.awt.Color;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Properties;
import java.util.logging.Level;
import javax.sql.RowSet;
import org.compiere.print.MPrintColor;
import org.compiere.util.CLogMgt;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;
public class MTree extends MTree_Base
{
private static final long serialVersionUID = -6412057411585787707L;
public MTree (Properties ctx,
int AD_Tree_ID, String trxName)
{
super (ctx, AD_Tree_ID, trxName);
}
public MTree (Properties ctx,
int AD_Tree_ID,
boolean editable, boolean clientTree, String trxName)
{
this (ctx, AD_Tree_ID, editable, clientTree, false, trxName);
}
public MTree (Properties ctx,
int AD_Tree_ID,
boolean editable, boolean clientTree, boolean allNodes, String trxName)
{
this (ctx, AD_Tree_ID, trxName);
m_editable = editable;
int AD_User_ID;
if (allNodes)
AD_User_ID = -1;
else
AD_User_ID = Env.getContextAsInt(ctx, "AD_User_ID");
m_clientTree = clientTree;
log.info("AD_Tree_ID=" + AD_Tree_ID
+ ", AD_User_ID=" + AD_User_ID
+ ", Editable=" + editable
+ ", OnClient=" + clientTree);
loadNodes(AD_User_ID);
}
private boolean m_editable = false;
private MTreeNode m_root = null;
private ArrayList<MTreeNode> m_buffer = new ArrayList<MTreeNode>();
private RowSet m_nodeRowSet;
private boolean m_clientTree = true;
private HashMap<Integer, ArrayList<Integer>> m_nodeIdMap;
private static CLogger s_log = CLogger.getCLogger(MTree.class);
{
s_log.config(keyColumnName);
if (keyColumnName == null || keyColumnName.length() == 0)
return 0;
String TreeType = null;
if (keyColumnName.equals("AD_Menu_ID"))
TreeType = TREETYPE_Menu;
else if (keyColumnName.equals("C_ElementValue_ID"))
TreeType = TREETYPE_ElementValue;
else if (keyColumnName.equals("M_Product_ID"))
TreeType = TREETYPE_Product;
else if (keyColumnName.equals("C_BPartner_ID"))
TreeType = TREETYPE_BPartner;
else if (keyColumnName.equals("AD_Org_ID"))
TreeType = TREETYPE_Organization;
else if (keyColumnName.equals("C_Project_ID"))
TreeType = TREETYPE_Project;
else if (keyColumnName.equals("M_ProductCategory_ID"))
TreeType = TREETYPE_ProductCategory;
else if (keyColumnName.equals("M_BOM_ID"))
TreeType = TREETYPE_BoM;
else if (keyColumnName.equals("C_SalesRegion_ID"))
TreeType = TREETYPE_SalesRegion;
else if (keyColumnName.equals("C_Campaign_ID"))
TreeType = TREETYPE_Campaign;
else if (keyColumnName.equals("C_Activity_ID"))
TreeType = TREETYPE_Activity;
else if (keyColumnName.equals("CM_CStage_ID"))
TreeType = TREETYPE_CMContainerStage;
else if (keyColumnName.equals("CM_Container_ID"))
TreeType = TREETYPE_CMContainer;
else if (keyColumnName.equals("CM_Media_ID"))
TreeType = TREETYPE_CMMedia;
else if (keyColumnName.equals("CM_Template_ID"))
TreeType = TREETYPE_CMTemplate;
else
{
s_log.log(Level.SEVERE, "Could not map " + keyColumnName);
return 0;
}
int AD_Tree_ID = 0;
String sql = "SELECT AD_Tree_ID, Name FROM AD_Tree "
+ "WHERE AD_Client_ID=? AND TreeType=? AND IsActive='Y' AND IsAllNodes='Y' "
+ "ORDER BY IsDefault DESC, AD_Tree_ID";
try
{
PreparedStatement pstmt = DB.prepareStatement(sql, null);
pstmt.setInt(1, AD_Client_ID);
pstmt.setString(2, TreeType);
ResultSet rs = pstmt.executeQuery();
if (rs.next())
AD_Tree_ID = rs.getInt(1);
rs.close();
pstmt.close();
}
catch (SQLException e)
{
s_log.log(Level.SEVERE, sql, e);
}
return AD_Tree_ID;
}
{
StringBuffer sql = new StringBuffer("SELECT "
+ "tn.Node_ID,tn.Parent_ID,tn.SeqNo,tb.IsActive "
+ "FROM ").append(getNodeTableName()).append(" tn"
+ " LEFT OUTER JOIN AD_TreeBar tb ON (tn.AD_Tree_ID=tb.AD_Tree_ID"
+ " AND tn.Node_ID=tb.Node_ID "
+ (AD_User_ID != -1 ? " AND tb.AD_User_ID=? ": "")
+ ") "
+ "WHERE tn.AD_Tree_ID=?");
if (!m_editable)
sql.append(" AND tn.IsActive='Y'");
sql.append(" ORDER BY COALESCE(tn.Parent_ID, -1), tn.SeqNo");
log.finest(sql.toString());
try
{
getNodeDetails();
PreparedStatement pstmt = DB.prepareStatement(sql.toString(), get_TrxName());
int idx = 1;
if (AD_User_ID != -1)
pstmt.setInt(idx++, AD_User_ID);
pstmt.setInt(idx++, getAD_Tree_ID());
ResultSet rs = pstmt.executeQuery();
m_root = new MTreeNode (0, 0, getName(), getDescription(), 0, true, null, false, null);
while (rs.next())
{
int node_ID = rs.getInt(1);
int parent_ID = rs.getInt(2);
int seqNo = rs.getInt(3);
boolean onBar = (rs.getString(4) != null);
if (node_ID == 0 && parent_ID == 0)
;
else
addToTree (node_ID, parent_ID, seqNo, onBar);
}
rs.close();
pstmt.close();
m_nodeRowSet = null;
m_nodeIdMap = null;
}
catch (SQLException e)
{
log.log(Level.SEVERE, sql.toString(), e);
m_nodeRowSet = null;
m_nodeIdMap = null;
}
if (m_buffer.size() != 0)
{
log.finest("clearing buffer - Adding to: " + m_root);
for (int i = 0; i < m_buffer.size(); i++)
{
MTreeNode node = (MTreeNode)m_buffer.get(i);
MTreeNode parent = m_root.findNode(node.getParent_ID());
if (parent != null && parent.getAllowsChildren())
{
parent.add(node);
int sizeBeforeCheckBuffer = m_buffer.size();
checkBuffer(node);
if (sizeBeforeCheckBuffer == m_buffer.size())
m_buffer.remove(i);
i = -1;
}
}
}
if (m_buffer.size() != 0)
{
log.severe ("Nodes w/o parent - adding to root - " + m_buffer);
for (int i = 0; i < m_buffer.size(); i++)
{
MTreeNode node = (MTreeNode)m_buffer.get(i);
m_root.add(node);
int sizeBeforeCheckBuffer = m_buffer.size();
checkBuffer(node);
if (sizeBeforeCheckBuffer == m_buffer.size())
m_buffer.remove(i);
i = -1;
}
if (m_buffer.size() != 0)
log.severe ("Still nodes in Buffer - " + m_buffer);
}
if (!m_editable && m_root.getChildCount() > 0)
trimTree();
if (CLogMgt.isLevelFinest() || m_root.getChildCount() == 0)
log.fine("ChildCount=" + m_root.getChildCount());
}
private void addToTree (
int node_ID,
int parent_ID,
int seqNo,
boolean onBar)
{
MTreeNode child = getNodeDetail (node_ID, parent_ID, seqNo, onBar);
if (child == null)
return;
MTreeNode parent = null;
if (m_root != null)
parent = m_root.findNode (parent_ID);
if (parent != null && parent.getAllowsChildren())
{
parent.add(child);
if (m_buffer.size() > 0)
checkBuffer(child);
}
else
m_buffer.add(child);
}
{
if (!newNode.isSummary() || !newNode.getAllowsChildren())
return;
for (int i = 0; i < m_buffer.size(); i++)
{
MTreeNode node = (MTreeNode)m_buffer.get(i);
if (node.getParent_ID() == newNode.getNode_ID())
{
try
{
newNode.add(node);
}
catch (Exception e)
{
log.severe("Adding " + node.getName()
+ " to " + newNode.getName() + ": " + e.getMessage());
}
m_buffer.remove(i);
i--;
}
}
}
{
StringBuffer sqlNode = new StringBuffer();
String sourceTable = "t";
String fromClause = getSourceTableName(false);
String columnNameX = getSourceTableName(true);
String color = getActionColorName();
if (getTreeType().equals(TREETYPE_Menu))
{
boolean base = Env.isBaseLanguage(p_ctx, "AD_Menu");
sourceTable = "m";
if (base)
sqlNode.append("SELECT m.AD_Menu_ID, m.Name,m.Description,m.IsSummary,m.Action, "
+ "m.AD_Window_ID, m.AD_Process_ID, m.AD_Form_ID, m.AD_Workflow_ID, m.AD_Task_ID, m.AD_Workbench_ID "
+ ", m.AD_Browse_ID "
+ "FROM AD_Menu m");
else
sqlNode.append("SELECT m.AD_Menu_ID, t.Name,t.Description,m.IsSummary,m.Action, "
+ "m.AD_Window_ID, m.AD_Process_ID, m.AD_Form_ID, m.AD_Workflow_ID, m.AD_Task_ID, m.AD_Workbench_ID "
+ ", m.AD_Browse_ID "
+ "FROM AD_Menu m, AD_Menu_Trl t");
if (!base)
sqlNode.append(" WHERE m.AD_Menu_ID=t.AD_Menu_ID AND t.AD_Language='")
.append(Env.getAD_Language(p_ctx)).append("'");
if (!m_editable)
{
boolean hasWhere = sqlNode.indexOf(" WHERE ") != -1;
sqlNode.append(hasWhere ? " AND " : " WHERE ").append("m.IsActive='Y' ");
}
if (!MClient.get(getCtx()).isUseBetaFunctions())
{
boolean hasWhere = sqlNode.indexOf(" WHERE ") != -1;
sqlNode.append(hasWhere ? " AND " : " WHERE ");
sqlNode.append("(m.AD_Window_ID IS NULL OR EXISTS (SELECT * FROM AD_Window w WHERE m.AD_Window_ID=w.AD_Window_ID AND w.IsBetaFunctionality='N'))")
.append(" AND (m.AD_Process_ID IS NULL OR EXISTS (SELECT * FROM AD_Process p WHERE m.AD_Process_ID=p.AD_Process_ID AND p.IsBetaFunctionality='N'))")
.append(" AND (m.AD_Workflow_ID IS NULL OR EXISTS (SELECT * FROM AD_Workflow wf WHERE m.AD_Workflow_ID=wf.AD_Workflow_ID AND wf.IsBetaFunctionality='N'))")
.append(" AND (m.AD_Form_ID IS NULL OR EXISTS (SELECT * FROM AD_Form f WHERE m.AD_Form_ID=f.AD_Form_ID AND f.IsBetaFunctionality='N'))")
.append(" AND (m.AD_Browse_ID IS NULL OR EXISTS (SELECT * FROM AD_Browse b WHERE m.AD_Browse_ID=b.AD_Browse_ID AND b.IsBetaFunctionality='N'))");
}
if (!m_editable)
{
boolean hasWhere = sqlNode.indexOf(" WHERE ") != -1;
sqlNode.append(hasWhere ? " AND " : " WHERE ");
sqlNode.append("(m.AD_Form_ID IS NULL OR EXISTS (SELECT * FROM AD_Form f WHERE m.AD_Form_ID=f.AD_Form_ID AND ");
if (m_clientTree)
sqlNode.append("f.Classname");
else
sqlNode.append("f.JSPURL");
sqlNode.append(" IS NOT NULL))");
}
}
else
{
if (columnNameX == null)
throw new IllegalArgumentException("Unknown TreeType=" + getTreeType());
sqlNode.append("SELECT t.").append(columnNameX)
.append("_ID,t.Name,t.Description,t.IsSummary,").append(color)
.append(" FROM ").append(fromClause);
if (!m_editable)
sqlNode.append(" WHERE t.IsActive='Y'");
}
String sql = sqlNode.toString();
if (!m_editable)
sql = MRole.getDefault(getCtx(), false).addAccessSQL(sql,
sourceTable, MRole.SQL_FULLYQUALIFIED, m_editable);
log.fine(sql);
m_nodeRowSet = DB.getRowSet (sql);
m_nodeIdMap = new HashMap<Integer, ArrayList<Integer>>(50);
try
{
m_nodeRowSet.beforeFirst();
int i = 0;
while (m_nodeRowSet.next())
{
i++;
int node = m_nodeRowSet.getInt(1);
Integer nodeId = Integer.valueOf(node);
ArrayList<Integer> list = m_nodeIdMap.get(nodeId);
if (list == null)
{
list = new ArrayList<Integer>(5);
m_nodeIdMap.put(nodeId, list);
}
list.add(Integer.valueOf(i));
}
} catch (SQLException e)
{
log.log(Level.SEVERE, "", e);
}
}
private MTreeNode
getNodeDetail (
int node_ID,
int parent_ID,
int seqNo,
boolean onBar)
{
MTreeNode retValue = null;
try
{
ArrayList<Integer> nodeList = m_nodeIdMap.get(Integer.valueOf(node_ID));
int size = nodeList != null ? nodeList.size() : 0;
int i = 0;
while (i < size)
{
Integer nodeId = nodeList.get(i);
i++;
m_nodeRowSet.absolute(nodeId.intValue());
int node = m_nodeRowSet.getInt(1);
if (node_ID != node)
continue;
int index = 2;
String name = m_nodeRowSet.getString(index++);
String description = m_nodeRowSet.getString(index++);
boolean isSummary = "Y".equals(m_nodeRowSet.getString(index++));
String actionColor = m_nodeRowSet.getString(index++);
if (getTreeType().equals(TREETYPE_Menu) && !isSummary)
{
int AD_Window_ID = m_nodeRowSet.getInt(index++);
int AD_Process_ID = m_nodeRowSet.getInt(index++);
int AD_Form_ID = m_nodeRowSet.getInt(index++);
int AD_Workflow_ID = m_nodeRowSet.getInt(index++);
int AD_Task_ID = m_nodeRowSet.getInt(index++);
int AD_Workbench_ID = m_nodeRowSet.getInt(index++);
int AD_Browse_ID = m_nodeRowSet.getInt(index++);
MRole role = MRole.getDefault(getCtx(), false);
Boolean access = null;
if (X_AD_Menu.ACTION_Window.equals(actionColor))
access = role.getWindowAccess(AD_Window_ID);
else if (X_AD_Menu.ACTION_Process.equals(actionColor)
|| X_AD_Menu.ACTION_Report.equals(actionColor))
access = role.getProcessAccess(AD_Process_ID);
else if (X_AD_Menu.ACTION_Form.equals(actionColor))
access = role.getFormAccess(AD_Form_ID);
else if (X_AD_Menu.ACTION_SmartBrowse.equals(actionColor))
access = role.getBrowseAccess(AD_Browse_ID);
else if (X_AD_Menu.ACTION_WorkFlow.equals(actionColor))
access = role.getWorkflowAccess(AD_Workflow_ID);
else if (X_AD_Menu.ACTION_Task.equals(actionColor))
access = role.getTaskAccess(AD_Task_ID);
if (access != null
|| m_editable)
{
retValue = new MTreeNode (node_ID, seqNo,
name, description, parent_ID, isSummary,
actionColor, onBar, null);
}
}
else
{
Color color = null;
if (actionColor != null && !getTreeType().equals(TREETYPE_Menu))
{
MPrintColor printColor = MPrintColor.get(getCtx(), actionColor);
if (printColor != null)
color = printColor.getColor();
}
retValue = new MTreeNode (node_ID, seqNo,
name, description, parent_ID, isSummary,
null, onBar, color);
}
}
}
catch (SQLException e)
{
log.log(Level.SEVERE, "", e);
}
return retValue;
}
{
boolean needsTrim = m_root != null;
while (needsTrim)
{
needsTrim = false;
Enumeration en = m_root.preorderEnumeration();
while (m_root.getChildCount() > 0 && en.hasMoreElements())
{
MTreeNode nd = (MTreeNode)en.nextElement();
if (nd.isSummary() && nd.getChildCount() == 0)
{
nd.removeFromParent();
needsTrim = true;
}
}
}
}
{
Enumeration en = m_root.preorderEnumeration();
int count = 0;
while (en.hasMoreElements())
{
StringBuffer sb = new StringBuffer();
MTreeNode nd = (MTreeNode)en.nextElement();
for (int i = 0; i < nd.getLevel(); i++)
sb.append(" ");
sb.append("ID=").append(nd.getNode_ID())
.append(", SeqNo=").append(nd.getSeqNo())
.append(" ").append(nd.getName());
System.out.println(sb.toString());
count++;
}
System.out.println("Count=" + count);
}
{
return m_root;
}
public boolean ()
{
return TREETYPE_Menu.equals(getTreeType());
}
{
return TREETYPE_Product.equals(getTreeType());
}
{
return TREETYPE_BPartner.equals(getTreeType());
}
{
StringBuffer sb = new StringBuffer("MTree[");
sb.append("AD_Tree_ID=").append(getAD_Tree_ID())
.append(", Name=").append(getName());
sb.append("]");
return sb.toString();
}
}