Java tutorial
/* ************************************************************************* * The contents of this file are subject to the Openbravo Public License * Version 1.1 (the "License"), being the Mozilla Public License * Version 1.1 with a permitted attribution clause; you may not use this * file except in compliance with the License. You may obtain a copy of * the License at http://www.openbravo.com/legal/license.html * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * The Original Code is Openbravo ERP. * The Initial Developer of the Original Code is Openbravo SLU * All portions are Copyright (C) 2001-2013 Openbravo SLU * All Rights Reserved. * Contributor(s): ______________________________________. ************************************************************************ */ package org.openbravo.erpCommon.utility; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; import org.hibernate.criterion.Restrictions; import org.openbravo.base.secureApp.HttpSecureAppServlet; import org.openbravo.base.secureApp.VariablesSecureApp; import org.openbravo.base.structure.BaseOBObject; import org.openbravo.client.application.GlobalMenu; import org.openbravo.dal.core.OBContext; import org.openbravo.dal.service.OBCriteria; import org.openbravo.dal.service.OBDal; import org.openbravo.dal.service.OBQuery; import org.openbravo.data.Sqlc; import org.openbravo.model.ad.datamodel.Table; import org.openbravo.model.ad.ui.Tab; import org.openbravo.model.ad.utility.Tree; import org.openbravo.utils.Replace; import org.openbravo.xmlEngine.XmlDocument; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver; /** * @author Fernando Iriazabal * * Manage the composition of the tree data for the tree window types. */ public class WindowTree extends HttpSecureAppServlet { private static final long serialVersionUID = 1L; private static final String CHILD_SHEETS = "frameWindowTreeF3"; private static List<String> nodeIdList = new ArrayList<String>(); @Inject GlobalMenu menu; public void init(ServletConfig config) { super.init(config); boolHist = false; } public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { VariablesSecureApp vars = new VariablesSecureApp(request); // Checking the window invoking the tree is accessible if (!hasGeneralAccess(vars, "W", vars.getStringParameter("inpTabId"))) { bdErrorGeneralPopUp(request, response, Utility.messageBD(this, "Error", vars.getLanguage()), Utility.messageBD(this, "AccessTableNoView", vars.getLanguage())); } if (vars.commandIn("DEFAULT", "TAB")) { String strTabId = vars.getGlobalVariable("inpTabId", "WindowTree|tabId"); Tab tab = OBDal.getInstance().get(Tab.class, strTabId); Table table = tab.getTable(); OBCriteria<Tree> adTreeCriteria = OBDal.getInstance().createCriteria(Tree.class); adTreeCriteria.add(Restrictions.eq(Tree.PROPERTY_TABLE, table)); adTreeCriteria.add(Restrictions.eq(Tree.PROPERTY_CLIENT, OBContext.getOBContext().getCurrentClient())); adTreeCriteria.setFilterOnReadableOrganization(false); Tree adTree = (Tree) adTreeCriteria.uniqueResult(); String strTreeID = ""; if (adTree != null) { strTreeID = adTree.getId(); } else { String key = WindowTreeData.selectKey(this, strTabId); { String TreeType = WindowTreeUtility.getTreeType(key); WindowTreeData[] data = WindowTreeData.selectTreeID(this, Utility.getContext(this, vars, "#User_Client", ""), TreeType); if (data != null && data.length > 0) strTreeID = data[0].id; } } if (strTreeID.equals("")) advisePopUp(request, response, "ERROR", Utility.messageBD(this, "Error", vars.getLanguage()), Utility.messageBD(this, "AccessTableNoView", vars.getLanguage())); else printPageDataSheet(response, vars, strTabId); } else if (vars.commandIn("ASSIGN")) { String strTabId = vars.getRequiredStringParameter("inpTabId"); String strTop = vars.getRequiredStringParameter("inpTop"); String strLink = vars.getRequiredStringParameter("inpLink"); String strChild = vars.getStringParameter("inpChild", "N"); String strResult = WindowTreeChecks.checkChanges(this, vars, strTabId, strTop, strLink, strChild.equals("Y")); if (strResult.equals("")) changeNode(vars, strTabId, strTop, strLink, strChild); else { vars.setSessionValue("WindowTree|message", strResult); } vars.setSessionValue("WindowTree|tabId", strTabId); PrintWriter out = response.getWriter(); if (strResult != "") { // create OBError and serizalize it using JSON OBError error = new OBError(); error.setType("Error"); error.setTitle("Error"); error.setMessage(strResult); XStream xs = new XStream(new JettisonMappedXmlDriver()); xs.alias("OBError", OBError.class); strResult = xs.toXML(error); } out.print(strResult); out.close(); } else throw new ServletException(); } /** * Main method to build the html for the tree. * * @param vars * Handler for the session info. * @param key * key column name. * @param editable * is editable? * @param strTabId * id of the tab. * @return String html with the tree. * @throws ServletException */ private String loadNodes(VariablesSecureApp vars, String key, boolean editable, String strTabId) throws ServletException { String TreeType = null; String TreeID = ""; String TreeName = ""; String TreeDescription = ""; StringBuffer menu = new StringBuffer(); if (key == null || key.isEmpty()) { Tab tab = OBDal.getInstance().get(Tab.class, strTabId); Table table = tab.getTable(); OBCriteria<Tree> adTreeCriteria = OBDal.getInstance().createCriteria(Tree.class); adTreeCriteria.add(Restrictions.eq(Tree.PROPERTY_TABLE, table)); adTreeCriteria.add(Restrictions.eq(Tree.PROPERTY_CLIENT, OBContext.getOBContext().getCurrentClient())); adTreeCriteria.setFilterOnReadableOrganization(false); Tree adTree = (Tree) adTreeCriteria.uniqueResult(); TreeID = adTree.getId(); TreeName = adTree.getName(); TreeDescription = adTree.getDescription(); TreeType = adTree.getTypeArea(); } else { TreeType = WindowTreeUtility.getTreeType(key); WindowTreeData[] data = WindowTreeData.selectTreeID(this, Utility.getContext(this, vars, "#User_Client", ""), TreeType); if (data == null || data.length == 0) { log4j.error( "WindowTree.loadNodes() - Unknown TreeNode: TreeType " + TreeType + " - TreeKey " + key); throw new ServletException("WindowTree.loadNodes() - Unknown TreeNode"); } else { TreeID = data[0].id; TreeName = data[0].name; TreeDescription = data[0].description; } } if (log4j.isDebugEnabled()) log4j.debug("WindowTree.loadNodes() - TreeType: " + TreeType + " || TreeID: " + TreeID); menu.append("\n<ul class=\"dhtmlgoodies_tree\">\n"); menu.append(WindowTreeUtility.addNodeElement(TreeName, TreeDescription, CHILD_SHEETS, true, "", strDireccion, "clickItem(0, '" + Replace.replace(TreeName, "'", "\\'") + "', 'N');", "dblClickItem(0);", true, "0", "")); WindowTreeData[] wtd = WindowTreeUtility.getTree(this, vars, TreeType, TreeID, editable, "", "", strTabId); Map<String, List<WindowTreeData>> wtdTree = buildTree(wtd); menu.append(generateTree(wtd, wtdTree, strDireccion, "0", true, strTabId)); menu.append("\n</ul>\n"); nodeIdList = null; return menu.toString(); } /** * Generates the tree for the html. * * @param data * Array with the tree elements. * @param strDireccion * String with the path for the urls. * @param indice * String with the index. * @param isFirst * Indicates if is the first or not. * @return String html with the tree. */ private String generateTree(WindowTreeData[] data, Map<String, List<WindowTreeData>> wtdTree, String strDireccion, String indice, boolean isFirst, String strTabId) { if (data == null || data.length == 0) return ""; if (log4j.isDebugEnabled()) log4j.debug("WindowTree.generateTree() - data: " + data.length); if (indice == null) indice = "0"; boolean hayDatos = false; StringBuffer strResultado = new StringBuffer(); strResultado.append("<ul>"); isFirst = false; List<WindowTreeData> subList = wtdTree.get(indice); if (subList != null) { List<WindowTreeData> filteredSubList = applyWhereClause(subList, strTabId); for (WindowTreeData elem : subList) { hayDatos = true; String strHijos = generateTree(data, wtdTree, strDireccion, elem.nodeId, isFirst, strTabId); // if elem is present in filtered sublist click action is allowed, else disabled if (filteredSubList.contains(elem)) { strResultado.append(WindowTreeUtility.addNodeElement(elem.name, elem.description, CHILD_SHEETS, elem.issummary.equals("Y"), WindowTreeUtility.windowType(elem.action), strDireccion, "clickItem('" + elem.nodeId + "', '" + Replace.replace(elem.name, "'", "\\'") + "', '" + elem.issummary + "');", "dblClickItem('" + elem.nodeId + "');", !strHijos.equals(""), elem.nodeId, elem.action)); } else { strResultado.append(WindowTreeUtility.addNodeElement(elem.name, elem.description, CHILD_SHEETS, elem.issummary.equals("Y"), WindowTreeUtility.windowType(elem.action), strDireccion, null, null, !strHijos.equals(""), elem.nodeId, elem.action)); } strResultado.append(strHijos); } } strResultado.append("</li></ul>"); return (hayDatos ? strResultado.toString() : ""); } /* * Retrieves the tab level hqlWhereClause and applies them to the current TreeData list and * returns the filtered list. sqlWhereClause is not applied in the tab, so not applied here. Uses * a global static list nodeIdList to fetch it only once though the method is called recursively. */ private List<WindowTreeData> applyWhereClause(List<WindowTreeData> subList, String strTabId) { String entityName = null, hqlWhereClause = null; try { OBContext.setAdminMode(); Tab tabData = OBDal.getInstance().get(org.openbravo.model.ad.ui.Tab.class, strTabId); if (tabData != null) { entityName = tabData.getTable().getName(); hqlWhereClause = tabData.getHqlwhereclause(); } } catch (Exception e) { log4j.error("Exception while retrieving hqlWhereClause " + e); } finally { OBContext.restorePreviousMode(); } List<WindowTreeData> newSubList = new ArrayList<WindowTreeData>(); if (hqlWhereClause != null && !hqlWhereClause.trim().isEmpty()) { hqlWhereClause = hqlWhereClause.replaceAll("\\be.", ""); OBQuery<BaseOBObject> entityResults = OBDal.getInstance().createQuery("" + entityName + "", hqlWhereClause); if (nodeIdList == null) { nodeIdList = new ArrayList<String>(); } if (nodeIdList.size() == 0 && nodeIdList.size() != entityResults.count()) { ScrollableResults entityData = entityResults.scroll(ScrollMode.FORWARD_ONLY); int clearEachLoops = 100; int i = 0; try { while (entityData.next()) { i++; BaseOBObject entity = (BaseOBObject) entityData.get()[0]; if (entity.getId() != null) { nodeIdList.add(entity.getId().toString()); } if (i % clearEachLoops == 0) { OBDal.getInstance().getSession().clear(); } } } finally { entityData.close(); } } for (WindowTreeData elem : subList) { if (nodeIdList.contains(elem.nodeId)) { newSubList.add(elem); } } } else { newSubList = subList; } return newSubList; } private static Map<String, List<WindowTreeData>> buildTree(WindowTreeData[] input) { Map<String, List<WindowTreeData>> resMap = new HashMap<String, List<WindowTreeData>>(); for (WindowTreeData elem : input) { List<WindowTreeData> list = resMap.get(elem.parentId); if (list == null) { list = new ArrayList<WindowTreeData>(); } list.add(elem); resMap.put(elem.parentId, list); } return resMap; } /** * Prints the tree page. * * @param response * Handler to the response. * @param vars * Handler for the session info. * @param TabId * Tab id. * @throws IOException * @throws ServletException */ private void printPageDataSheet(HttpServletResponse response, VariablesSecureApp vars, String TabId) throws IOException, ServletException { if (log4j.isDebugEnabled()) log4j.debug("Output: Tree's screen for the tab: " + TabId); OBError defaultInfo = new OBError(); defaultInfo.setType("INFO"); defaultInfo.setTitle(Utility.messageBD(this, "Info", vars.getLanguage())); defaultInfo.setMessage(Utility.messageBD(this, "TreeInfo", vars.getLanguage())); vars.setMessage("WindowTree", defaultInfo); XmlDocument xmlDocument = xmlEngine.readXmlTemplate("org/openbravo/erpCommon/utility/WindowTree") .createXmlDocument(); xmlDocument.setParameter("language", "defaultLang=\"" + vars.getLanguage() + "\";"); xmlDocument.setParameter("directory", "var baseDirectory = \"" + strReplaceWith + "/\";\n"); xmlDocument.setParameter("theme", vars.getTheme()); String strTreeID = ""; Tab tab = OBDal.getInstance().get(Tab.class, TabId); Table table = tab.getTable(); OBCriteria<Tree> adTreeCriteria = OBDal.getInstance().createCriteria(Tree.class); adTreeCriteria.add(Restrictions.eq(Tree.PROPERTY_TABLE, table)); adTreeCriteria.add(Restrictions.eq(Tree.PROPERTY_CLIENT, OBContext.getOBContext().getCurrentClient())); adTreeCriteria.setFilterOnReadableOrganization(false); Tree adTree = (Tree) adTreeCriteria.uniqueResult(); String key = ""; if (adTree != null) { strTreeID = adTree.getId(); } else { key = WindowTreeData.selectKey(this, TabId); { String TreeType = WindowTreeUtility.getTreeType(key); WindowTreeData[] data = WindowTreeData.selectTreeID(this, Utility.getContext(this, vars, "#User_Client", ""), TreeType); if (data != null && data.length > 0) strTreeID = data[0].id; } } WindowTreeData[] data = WindowTreeData.selectTabName(this, TabId); xmlDocument.setParameter("description", data[0].name); xmlDocument.setParameter("page", Utility.getTabURL(TabId, "E", true)); xmlDocument.setParameter("menu", loadNodes(vars, key, WindowTreeData.selectEditable(this, TabId).equals("Y"), TabId)); xmlDocument.setParameter("treeID", strTreeID); xmlDocument.setParameter("tabID", TabId); key = "inp" + Sqlc.TransformaNombreColumna(key); xmlDocument.setParameter("keyField", key); xmlDocument.setParameter("keyFieldScript", "function getKeyField() {\n return document.frmMain." + key + ";\n}\n"); try { OBError myMessage = vars.getMessage("WindowTree"); vars.removeMessage("WindowTree"); if (myMessage != null) { xmlDocument.setParameter("messageType", myMessage.getType()); xmlDocument.setParameter("messageTitle", myMessage.getTitle()); xmlDocument.setParameter("messageMessage", myMessage.getMessage()); } } catch (Exception ex) { ex.printStackTrace(); } response.setContentType("text/html; charset=UTF-8"); PrintWriter out = response.getWriter(); out.println(xmlDocument.print()); out.close(); } /** * Makes the change of position of the elements in the tree. * * It positions the node and moves down all the nodes after this one. * * For menu tree it looks whether the current node and the ones after that are within a module in * development. It searchs the first node after the current one that is not in development and * modifies the seqno for the current one (regardless it is in development or not) and the ones * bellow it that are in development. * * @param vars * Handler for the session info. * @param strTabId * Tab id. * @param strTop * Parent node id. * @param strLink * Id of the node to change. * @param strChild * String indicating if is a child or not of the parent node (Y|N). * @throws ServletException */ private void changeNode(VariablesSecureApp vars, String strTabId, String strTop, String strLink, String strChild) throws ServletException { String key = WindowTreeData.selectKey(this, strTabId); String TreeType = WindowTreeUtility.getTreeType(key); String TreeID = ""; String strParent = strTop; boolean editable = WindowTreeData.selectEditable(this, strTabId).equals("Y"); if ("MM".equals(TreeType)) { // Editing Application Menu tree, invalidate menu cache manually as this update is not // captured by Listener because it is not done though DAL menu.invalidateCache(); } // Calculating the TreeID { Tab tab = OBDal.getInstance().get(Tab.class, strTabId); Table table = tab.getTable(); OBCriteria<Tree> adTreeCriteria = OBDal.getInstance().createCriteria(Tree.class); adTreeCriteria.add(Restrictions.eq(Tree.PROPERTY_TABLE, table)); adTreeCriteria.add(Restrictions.eq(Tree.PROPERTY_CLIENT, OBContext.getOBContext().getCurrentClient())); adTreeCriteria.setFilterOnReadableOrganization(false); Tree adTree = (Tree) adTreeCriteria.uniqueResult(); if (adTree != null) { TreeID = adTree.getId(); TreeType = adTree.getTable().getTreeType(); } else { WindowTreeData[] data = WindowTreeData.selectTreeID(this, Utility.getContext(this, vars, "#User_Client", ""), TreeType); if (data == null || data.length == 0) { log4j.error("WindowTree.loadNodes() - Unknown TreeNode"); throw new ServletException("WindowTree.loadNodes() - Unknown TreeNode"); } else { TreeID = data[0].id; } } } // Calculating the parent if (!strTop.equals("0")) { WindowTreeData[] data = WindowTreeUtility.getTree(this, vars, TreeType, TreeID, editable, "", strTop, strTabId); if (data == null || data.length == 0) { log4j.error("WindowTree.loadNodes() - Unknown Top Node"); throw new ServletException("WindowTree.loadNodes() - Unknown Top Node"); } if (!data[0].issummary.equals("Y") || !strChild.equals("Y")) { strParent = data[0].parentId; } } else strParent = strTop; WindowTreeData[] data = WindowTreeUtility.getTree(this, vars, TreeType, TreeID, editable, strParent, "", strTabId); int seqNo = 0; int add = 10; try { if (data == null || data.length == 0) { WindowTreeUtility.setNode(this, vars, TreeType, TreeID, strParent, strLink, Integer.toString(seqNo)); } else { boolean updated = false; boolean finish = false; if (strParent.equals(strTop)) { seqNo += add; WindowTreeUtility.setNode(this, vars, TreeType, TreeID, strParent, strLink, Integer.toString(seqNo)); updated = true; } for (int i = 0; !finish && i < data.length; i++) { if (!data[i].nodeId.equals(strLink)) { if (updated && !finish) { // update only elements after // the current one if (data[i].isindevelopment == null || data[i].isindevelopment.equals("") || data[i].isindevelopment.equals("Y")) { seqNo += add; WindowTreeUtility.setNode(this, vars, TreeType, TreeID, data[i].parentId, data[i].nodeId, Integer.toString(seqNo)); } else { finish = true; // update elements till one is // not in developement, then // finish } } if (!updated && data[i].nodeId.equals(strTop)) { // Calculate the addition for the range of modules // in development int j = 0; for (j = i + 1; j < data.length && (data[j].isindevelopment == null || data[j].isindevelopment.equals("") || data[j].isindevelopment.equals("Y")); j++) ; if (j == data.length) add = 10; // it is at the end it can be expanded // without problem else add = new Float( ((new Integer(data[j].seqno) - new Integer(data[i].seqno)) / (j - i + 1))) .intValue(); // Set the current node in its posisiton if (i == 0) seqNo = 10; else seqNo = new Integer(data[i].seqno).intValue() + add; WindowTreeUtility.setNode(this, vars, TreeType, TreeID, strParent, strLink, Integer.toString(seqNo)); updated = true; } } } if (!updated) WindowTreeUtility.setNode(this, vars, TreeType, TreeID, strParent, strLink, Integer.toString(seqNo)); } } catch (ServletException e) { log4j.error("WindowTree.changeNode() - Couldn't change the node: " + strLink); log4j.error("WindowTree.setNode() - error: " + e); throw new ServletException(e); } } public String getServletInfo() { return "Servlet that presents the tree of a TreeNode windo windoww"; } // end of getServletInfo() method }