/****************************************************************************** * Product: Adempiere ERP & CRM Smart Business Solution * * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * For the text or an alternative of this public license, you may reach us * * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * * or via info@compiere.org or http://www.compiere.org/license.html * *****************************************************************************/ package org.compiere.wf; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.logging.Level; import org.compiere.model.DocWorkflowMgr; import org.compiere.model.PO; import static org.compiere.model.SystemIDs.*; import org.compiere.process.ProcessInfo; import org.compiere.util.CLogger; import org.compiere.util.DB; import org.compiere.util.Env; import org.compiere.util.Evaluator; /** * Document Workflow Manager * * @author Jorg Janke * @version $Id: DocWorkflowManager.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $ */ public class DocWorkflowManager implements DocWorkflowMgr { /** * Get the singleton Document Workflow Manager instance * @return mgr */ public static DocWorkflowManager get() { if (s_mgr == null) s_mgr = new DocWorkflowManager(); return s_mgr; } // get // Set PO Workflow Manager static { PO.setDocWorkflowMgr(get()); } /** Document Workflow Manager */ private volatile static DocWorkflowManager s_mgr = null; /** Logger */ private static CLogger log = CLogger.getCLogger(DocWorkflowManager.class); /** * Doc Workflow Manager */ private DocWorkflowManager () { super (); if (s_mgr == null) s_mgr = this; } // DocWorkflowManager private int m_noCalled = 0; private int m_noStarted = 0; /** * Process Document Value Workflow * @param document document * @param AD_Table_ID table * @return true if WF started */ public boolean process (PO document, int AD_Table_ID) { m_noCalled++; MWorkflow[] wfs = MWorkflow.getDocValue (document.getCtx(), document.getAD_Client_ID(), AD_Table_ID , document.get_TrxName() // Bug 1568766 Trx should be kept all along the road ); if (wfs == null || wfs.length == 0) return false; boolean started = false; for (int i = 0; i < wfs.length; i++) { MWorkflow wf = wfs[i]; // We have a Document Workflow String logic = wf.getDocValueLogic(); if (logic == null || logic.length() == 0) { log.severe ("Workflow has no Logic - " + wf.getName()); continue; } // Re-check: Document must be same Client as workflow if (wf.getAD_Client_ID() != document.getAD_Client_ID()) continue; // Check Logic boolean sql = logic.startsWith("SQL="); if (sql && !testStart(wf, document)) { if (log.isLoggable(Level.FINE)) log.fine("SQL Logic evaluated to false (" + logic + ")"); continue; } if (!sql && !Evaluator.evaluateLogic(document, logic)) { if (log.isLoggable(Level.FINE)) log.fine("Logic evaluated to false (" + logic + ")"); continue; } // Start Workflow if (log.isLoggable(Level.FINE)) log.fine(logic); int AD_Process_ID = PROCESS_AD_WORKFLOW_DOCVALUE; // HARDCODED ProcessInfo pi = new ProcessInfo (wf.getName(), AD_Process_ID, AD_Table_ID, document.get_ID()); pi.setAD_User_ID (Env.getAD_User_ID(document.getCtx())); pi.setAD_Client_ID(document.getAD_Client_ID()); // if (wf.start(pi, document.get_TrxName()) != null) { if (log.isLoggable(Level.CONFIG)) log.config(wf.getName()); m_noStarted++; started = true; } } return started; } // process /** * Test Start condition * @param wf workflow * @param document document * @return true if WF should be started */ private boolean testStart (MWorkflow wf, PO document) { boolean retValue = false; String logic = wf.getDocValueLogic(); logic = logic.substring(4); // "SQL=" // String tableName = document.get_TableName(); String[] keyColumns = document.get_KeyColumns(); if (keyColumns.length != 1) { log.severe("Tables with more then one key column not supported - " + tableName + " = " + keyColumns.length); return false; } String keyColumn = keyColumns[0]; StringBuilder sql = new StringBuilder("SELECT ") .append(keyColumn).append(" FROM ").append(tableName) .append(" WHERE AD_Client_ID=? AND ") // #1 .append(keyColumn).append("=? AND ") // #2 .append(logic) // Duplicate Open Workflow test .append(" AND NOT EXISTS (SELECT * FROM AD_WF_Process wfp ") .append("WHERE wfp.AD_Table_ID=? AND wfp.Record_ID=") // #3 .append(tableName).append(".").append(keyColumn) .append(" AND wfp.AD_Workflow_ID=?") // #4 .append(" AND SUBSTR(wfp.WFState,1,1)='O')"); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement (sql.toString(), document.get_TrxName()); pstmt.setInt (1, wf.getAD_Client_ID()); pstmt.setInt (2, document.get_ID()); pstmt.setInt (3, document.get_Table_ID()); pstmt.setInt (4, wf.getAD_Workflow_ID()); rs = pstmt.executeQuery (); if (rs.next ()) retValue = true; } catch (Exception e) { log.log (Level.SEVERE, "Logic=" + logic + " - SQL=" + sql.toString(), e); } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } return retValue; } // testStart /** * String Representation * @return info */ @Override public String toString() { StringBuilder sb = new StringBuilder("DocWorkflowManager["); sb.append("Called=").append(m_noCalled) .append(",Stated=").append(m_noStarted) .append("]"); return sb.toString(); } // toString } // DocWorkflowManager