/****************************************************************************** * 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.model; import java.util.ArrayList; import java.util.Collections; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.StringTokenizer; import java.util.logging.Level; import javax.script.ScriptEngine; import org.adempiere.base.Core; import org.adempiere.base.event.EventManager; import org.adempiere.base.event.EventProperty; import org.adempiere.base.event.FactsEventData; import org.adempiere.base.event.IEventManager; import org.adempiere.base.event.IEventTopics; import org.adempiere.base.event.ImportEventData; import org.adempiere.base.event.LoginEventData; import org.adempiere.exceptions.AdempiereException; import org.adempiere.model.ImportValidator; import org.adempiere.process.ImportProcess; import org.compiere.acct.Fact; import org.compiere.util.CLogger; import org.compiere.util.Env; import org.compiere.util.KeyNamePair; import org.compiere.util.Util; import org.osgi.service.event.Event; /** * Model Validation Engine * * @author Jorg Janke * @version $Id: ModelValidationEngine.java,v 1.2 2006/07/30 00:58:38 jjanke Exp $ * * @author Teo Sarca, SC ARHIPAC SERVICE SRL *
  • FR [ 1670025 ] ModelValidator.afterLoadPreferences will be useful *
  • BF [ 1679692 ] fireDocValidate doesn't treat exceptions as errors *
  • FR [ 1724662 ] Support Email should contain model validators info *
  • FR [ 2788276 ] Data Import Validator * https://sourceforge.net/p/adempiere/feature-requests/712/ *
  • BF [ 2804135 ] Global FactsValidator are not invoked * https://sourceforge.net/p/adempiere/bugs/1936/ *
  • BF [ 2819617 ] NPE if script validator rule returns null * https://sourceforge.net/p/adempiere/bugs/1976/ * @author victor.perez@e-evolution.com, www.e-evolution.com *
  • BF [ 2947607 ] Model Validator Engine duplicate listeners */ public class ModelValidationEngine { /** * Get Singleton instance * @return singleton engine instance */ public synchronized static ModelValidationEngine get() { if (s_engine == null) s_engine = new ModelValidationEngine(); return s_engine; } // get /** Engine Singleton */ private static ModelValidationEngine s_engine = null; /** flag to indicate a missing model validation class */ private static String missingModelValidationMessage = ""; /** * Private Constructor. * Use {@link #get()} to get the singleton instance. */ private ModelValidationEngine () { super (); // Load global validators MTable table = MTable.get(Env.getCtx(), X_AD_ModelValidator.Table_ID); Query query = table.createQuery("IsActive='Y'", null); query.setOrderBy("SeqNo"); try { List entityTypes = query.list(); for (X_AD_ModelValidator entityType : entityTypes) { String className = entityType.getModelValidationClass(); if (className == null || className.length() == 0) continue; loadValidatorClass(null, className); } } catch (Exception e) { //logging to db will try to init ModelValidationEngine again! e.printStackTrace(); missingModelValidationMessage = missingModelValidationMessage + e.toString() + " global" + '\n'; } // Go through all Clients and start Validators MClient[] clients = MClient.getAll(Env.getCtx()); for (int i = 0; i < clients.length; i++) { String classNames = clients[i].getModelValidationClasses(); if (classNames == null || classNames.length() == 0) continue; loadValidatorClasses(clients[i], classNames); } } // ModelValidatorEngine /** * Load validation instances * @param client * @param classNames Java class name list separated by semicolon */ private void loadValidatorClasses(MClient client, String classNames) { StringTokenizer st = new StringTokenizer(classNames, ";"); while (st.hasMoreTokens()) { String className = null; try { className = st.nextToken(); if (className == null) continue; className = className.trim(); if (className.length() == 0) continue; // loadValidatorClass(client, className); } catch (Exception e) { //logging to db will try to init ModelValidationEngine again! e.printStackTrace(); missingModelValidationMessage = missingModelValidationMessage + e.toString() + " on tenant " + client.getName() + '\n'; } } } /** * Load validator instance * @param client * @param className */ private void loadValidatorClass(MClient client, String className) { try { // ModelValidator validator = null; validator = Core.getModelValidator(className); if (validator == null) { missingModelValidationMessage = missingModelValidationMessage + " Missing class " + className + (client != null ? (" on tenant " + client.getName()) : " global") + '\n'; } else { initialize(validator, client); } } catch (Exception e) { //logging to db will try to init ModelValidationEngine again! e.printStackTrace(); missingModelValidationMessage = missingModelValidationMessage + e.toString() + (client != null ? (" on tenant " + client.getName()) : " global") + '\n'; } } /** Logger */ private static CLogger log = CLogger.getCLogger(ModelValidationEngine.class); /** Validators */ private ArrayList m_validators = new ArrayList(); /** Model Change Listeners */ private Hashtable> m_modelChangeListeners = new Hashtable>(); /** Document Validation Listeners */ private Hashtable> m_docValidateListeners = new Hashtable>(); /** Accounting Facts Validation Listeners */ private Hashtable>m_factsValidateListeners = new Hashtable>(); /** Data Import Validation Listeners */ private Hashtable>m_impValidateListeners = new Hashtable>(); private ArrayList m_globalValidators = new ArrayList(); /** * Initialize and add validator to global or client validator list. * @param validator * @param client null for global validator, not null for client specific validator */ private void initialize(ModelValidator validator, MClient client) { if (client == null) m_globalValidators.add(validator); m_validators.add(validator); validator.initialize(this, client); } // initialize /** * Called when login is complete.
    * - Call {@link ModelValidator#login(int, int, int)} on register validators. * - Call script validator (AD_Table_ScriptValidator)
    * - Fire {@link IEventTopics#AFTER_LOGIN} OSGi event. * @param AD_Client_ID client * @param AD_Org_ID org * @param AD_Role_ID role * @param AD_User_ID user * @return error message or null */ public String loginComplete (int AD_Client_ID, int AD_Org_ID, int AD_Role_ID, int AD_User_ID) { for (int i = 0; i < m_validators.size(); i++) { ModelValidator validator = m_validators.get(i); if (AD_Client_ID == validator.getAD_Client_ID() || m_globalValidators.contains(validator)) { String error = validator.login(AD_Org_ID, AD_Role_ID, AD_User_ID); if (error != null && error.length() > 0) return error; } } // now process the script model validator for login List loginRules = MRule.getModelValidatorLoginRules (Env.getCtx()); if (loginRules != null) { for (MRule loginRule : loginRules) { // currently just JSR 223 supported if ( loginRule.getRuleType().equals(MRule.RULETYPE_JSR223ScriptingAPIs) && loginRule.getEventType().equals(MRule.EVENTTYPE_ModelValidatorLoginEvent)) { String error; try { ScriptEngine engine = loginRule.getScriptEngine(); if (engine == null) { throw new AdempiereException("Engine not found: " + loginRule.getEngineName()); } MRule.setContext(engine, Env.getCtx(), 0); // no window // now add the method arguments to the engine engine.put(MRule.ARGUMENTS_PREFIX + "Ctx", Env.getCtx()); engine.put(MRule.ARGUMENTS_PREFIX + "AD_Client_ID", AD_Client_ID); engine.put(MRule.ARGUMENTS_PREFIX + "AD_Org_ID", AD_Org_ID); engine.put(MRule.ARGUMENTS_PREFIX + "AD_Role_ID", AD_Role_ID); engine.put(MRule.ARGUMENTS_PREFIX + "AD_User_ID", AD_User_ID); Object retval = engine.eval(loginRule.getScript()); error = (retval == null ? "" : retval.toString()); } catch (Exception e) { e.printStackTrace(); error = e.toString(); } if (error != null && error.length() > 0) return error; } } } //now process osgi event handler LoginEventData eventData = new LoginEventData(AD_Client_ID, AD_Org_ID, AD_Role_ID, AD_User_ID); Event event = EventManager.newEvent(IEventTopics.AFTER_LOGIN, eventData); EventManager.getInstance().sendEvent(event); @SuppressWarnings("unchecked") List errors = (List) event.getProperty(IEventManager.EVENT_ERROR_MESSAGES); if (errors != null && !errors.isEmpty()) { Collections.reverse(errors); StringBuilder eventErrors = new StringBuilder(""); for (String error : errors) { eventErrors.append(error).append("
    "); } return eventErrors.toString(); } if ((AD_User_ID == SystemIDs.USER_SYSTEM || AD_User_ID == SystemIDs.USER_SUPERUSER) && AD_Role_ID == SystemIDs.ROLE_SYSTEM) ; // don't validate for user system on role system else if (! Util.isEmpty(missingModelValidationMessage)) { MSystem system = MSystem.get(Env.getCtx()); if (system.isFailOnMissingModelValidator()) return missingModelValidationMessage; } return null; } // loginComplete /** * Add Model Change Listener for a table * @param tableName table name * @param listener listener (global or tenant specific) */ public void addModelChange (String tableName, ModelValidator listener) { if (tableName == null || listener == null) return; // String propertyName = m_globalValidators.contains(listener) ? tableName + "*" : tableName + listener.getAD_Client_ID(); ArrayList list = m_modelChangeListeners.get(propertyName); if (list == null) { list = new ArrayList(); list.add(listener); m_modelChangeListeners.put(propertyName, list); } else list.add(listener); } // addModelValidator /** * Remove Model Change Listener for a table * @param tableName table name * @param listener listener (global or tenant specific) */ public void removeModelChange (String tableName, ModelValidator listener) { if (tableName == null || listener == null) return; String propertyName = m_globalValidators.contains(listener) ? tableName + "*" : tableName + listener.getAD_Client_ID(); ArrayList list = m_modelChangeListeners.get(propertyName); if (list == null) return; list.remove(listener); if (list.size() == 0) m_modelChangeListeners.remove(propertyName); } // removeModelValidator /** * Fire Model Change event of a table. * - Call {@link ModelValidator#modelChange(PO, int)} on register validators.
    * - Call script validator (AD_Table_ScriptValidator)
    * - Fire IEventTopics.PO_* OSGi event. * @param po PO instance for the event * @param changeType ModelValidator.TYPE_* * @return error message or NULL for no veto */ public String fireModelChange (PO po, int changeType) { if (po == null ) return null; String propertyName = po.get_TableName() + "*"; ArrayList list = m_modelChangeListeners.get(propertyName); if (list != null) { //ad_entitytype.modelvalidationclasses String error = fireModelChange(po, changeType, list); if (error != null && error.length() > 0) return error; } propertyName = po.get_TableName() + po.getAD_Client_ID(); list = m_modelChangeListeners.get(propertyName); if (list != null) { //ad_client.modelvalidationclasses String error = fireModelChange(po, changeType, list); if (error != null && error.length() > 0) return error; } // now process the script model validator for this event List scriptValidators = MTableScriptValidator.getModelValidatorRules( po.getCtx(), po.get_Table_ID(), ModelValidator.tableEventValidators[changeType]); if (scriptValidators != null) { for (MTableScriptValidator scriptValidator : scriptValidators) { MRule rule = MRule.get(po.getCtx(), scriptValidator.getAD_Rule_ID()); // currently just JSR 223 supported if ( rule != null && rule.isActive() && rule.getRuleType().equals(MRule.RULETYPE_JSR223ScriptingAPIs) && rule.getEventType().equals(MRule.EVENTTYPE_ModelValidatorTableEvent)) { String error; try { ScriptEngine engine = rule.getScriptEngine(); if (engine == null) { throw new AdempiereException("Engine not found: " + rule.getEngineName()); } MRule.setContext(engine, po.getCtx(), 0); // no window // now add the method arguments to the engine engine.put(MRule.ARGUMENTS_PREFIX + "Ctx", po.getCtx()); engine.put(MRule.ARGUMENTS_PREFIX + "PO", po); engine.put(MRule.ARGUMENTS_PREFIX + "Type", changeType); engine.put(MRule.ARGUMENTS_PREFIX + "Event", ModelValidator.tableEventValidators[changeType]); Object retval = engine.eval(rule.getScript()); error = (retval == null ? "" : retval.toString()); } catch (Exception e) { e.printStackTrace(); error = e.toString(); } if (error != null && error.length() > 0) return error; } } } //now process osgi event handlers Event event = EventManager.newEvent(ModelValidator.tableEventTopics[changeType], new EventProperty(EventManager.EVENT_DATA, po), new EventProperty(EventManager.TABLE_NAME_PROPERTY, po.get_TableName())); EventManager.getInstance().sendEvent(event); @SuppressWarnings("unchecked") List errors = (List) event.getProperty(IEventManager.EVENT_ERROR_MESSAGES); if (errors != null && !errors.isEmpty()) { Collections.reverse(errors); StringBuilder eventErrors = new StringBuilder(""); for (String error : errors) { eventErrors.append(error).append("
    "); } return eventErrors.toString(); } return null; } // fireModelChange /** * Fire model change event of a table.
    * - Call {@link ModelValidator#modelChange(PO, int)} on register validators. * @param po PO instance for the event * @param changeType ModelValidator.TYPE_* * @param list register validators * @return error message or null */ private String fireModelChange(PO po, int changeType, ArrayList list) { for (int i = 0; i < list.size(); i++) { try { ModelValidator validator = list.get(i); if (validator.getAD_Client_ID() == po.getAD_Client_ID() || m_globalValidators.contains(validator)) { String error = validator.modelChange(po, changeType); if (error != null && error.length() > 0) { if (log.isLoggable(Level.FINE)) { log.log(Level.FINE, "po="+po+" validator="+validator+" changeType="+changeType); } return error; } } } catch (Exception e) { //log the exception log.log(Level.SEVERE, e.getLocalizedMessage(), e); String error = e.getLocalizedMessage(); if (error == null) error = e.toString(); return error; } } return null; } /** * Add Document Validation Listener for a table * @param tableName table name * @param listener listener (global or tenant specific) */ public void addDocValidate (String tableName, ModelValidator listener) { if (tableName == null || listener == null) return; // String propertyName = m_globalValidators.contains(listener) ? tableName + "*" : tableName + listener.getAD_Client_ID(); ArrayList list = m_docValidateListeners.get(propertyName); if (list == null) { list = new ArrayList(); list.add(listener); m_docValidateListeners.put(propertyName, list); } else if (!list.contains(listener)) { list.add(listener); } } // addDocValidate /** * Remove Document Validation Listener of a table * @param tableName table name * @param listener listener (global or tenant specific) */ public void removeDocValidate (String tableName, ModelValidator listener) { if (tableName == null || listener == null) return; String propertyName = m_globalValidators.contains(listener) ? tableName + "*" : tableName + listener.getAD_Client_ID(); ArrayList list = m_docValidateListeners.get(propertyName); if (list == null) return; list.remove(listener); if (list.size() == 0) m_docValidateListeners.remove(propertyName); } // removeDocValidate /** * Fire Document Validation event of a table.
    * - Call {@link ModelValidator#docValidate(PO, int)} on register validators.
    * - Call script validator (AD_Table_ScriptValidator)
    * - Fire IEventTopics.DOC_* OSGi event. * @param po PO instance for the event * @param docTiming see ModelValidator.TIMING_ constants * @return error message or null */ public String fireDocValidate (PO po, int docTiming) { if (po == null) return null; String propertyName = po.get_TableName() + "*"; ArrayList list = m_docValidateListeners.get(propertyName); if (list != null) { //ad_entitytype.modelvalidationclasses String error = fireDocValidate(po, docTiming, list); if (error != null && error.length() > 0) return error; } propertyName = po.get_TableName() + po.getAD_Client_ID(); list = m_docValidateListeners.get(propertyName); if (list != null) { //ad_client.modelvalidationclasses String error = fireDocValidate(po, docTiming, list); if (error != null && error.length() > 0) return error; } // now process the script model validator for this event List scriptValidators = MTableScriptValidator.getModelValidatorRules( po.getCtx(), po.get_Table_ID(), ModelValidator.documentEventValidators[docTiming]); if (scriptValidators != null) { for (MTableScriptValidator scriptValidator : scriptValidators) { MRule rule = MRule.get(po.getCtx(), scriptValidator.getAD_Rule_ID()); // currently just JSR 223 supported if ( rule != null && rule.isActive() && rule.getRuleType().equals(MRule.RULETYPE_JSR223ScriptingAPIs) && rule.getEventType().equals(MRule.EVENTTYPE_ModelValidatorDocumentEvent)) { String error; try { ScriptEngine engine = rule.getScriptEngine(); if (engine == null) { throw new AdempiereException("Engine not found: " + rule.getEngineName()); } MRule.setContext(engine, po.getCtx(), 0); // no window // now add the method arguments to the engine engine.put(MRule.ARGUMENTS_PREFIX + "Ctx", po.getCtx()); engine.put(MRule.ARGUMENTS_PREFIX + "PO", po); engine.put(MRule.ARGUMENTS_PREFIX + "Type", docTiming); engine.put(MRule.ARGUMENTS_PREFIX + "Event", ModelValidator.documentEventValidators[docTiming]); Object retval = engine.eval(rule.getScript()); error = (retval == null ? "" : retval.toString()); } catch (Exception e) { e.printStackTrace(); error = e.toString(); } if (error != null && error.length() > 0) return error; } } } //now process osgi event handlers Event event = EventManager.newEvent(ModelValidator.documentEventTopics[docTiming], new EventProperty(EventManager.EVENT_DATA, po), new EventProperty(EventManager.TABLE_NAME_PROPERTY, po.get_TableName())); EventManager.getInstance().sendEvent(event); @SuppressWarnings("unchecked") List errors = (List) event.getProperty(IEventManager.EVENT_ERROR_MESSAGES); if (errors != null && !errors.isEmpty()) { Collections.reverse(errors); StringBuilder eventErrors = new StringBuilder(""); for (String error : errors) { eventErrors.append(error).append("
    "); } return eventErrors.toString(); } return null; } // fireDocValidate /** * Fire Document Validation event of a table.
    * - Call {@link ModelValidator#docValidate(PO, int)} on register validators. * @param po * @param docTiming * @param list register validators * @return error message or null */ private String fireDocValidate(PO po, int docTiming, ArrayList list) { for (int i = 0; i < list.size(); i++) { ModelValidator validator = null; try { validator = list.get(i); if (validator.getAD_Client_ID() == po.getAD_Client_ID() || m_globalValidators.contains(validator)) { String error = validator.docValidate(po, docTiming); if (error != null && error.length() > 0) { if (log.isLoggable(Level.FINE)) { log.log(Level.FINE, "po="+po+" validator="+validator+" timing="+docTiming); } return error; } } } catch (Exception e) { //log the stack trace log.log(Level.SEVERE, e.getLocalizedMessage(), e); // Exceptions are errors and should stop the document processing - teo_sarca [ 1679692 ] String error = e.getLocalizedMessage(); if (error == null) error = e.toString(); return error; } } return null; } /** * Add Accounting Facts Validation Listener * @param tableName table name * @param listener listener (global or tenant specific) */ public void addFactsValidate (String tableName, FactsValidator listener) { if (tableName == null || listener == null) return; // String propertyName = (listener instanceof ModelValidator && m_globalValidators.contains((ModelValidator)listener)) ? tableName + "*" : tableName + listener.getAD_Client_ID(); ArrayList list = m_factsValidateListeners.get(propertyName); if (list == null) { list = new ArrayList(); list.add(listener); m_factsValidateListeners.put(propertyName, list); } else list.add(listener); } // addFactsValidate /** * Add Import Validation Listener of an import table * @param importTableName table name * @param listener listener */ public void addImportValidate (String importTableName, ImportValidator listener) { String propertyName = importTableName + "*"; ArrayList list = m_impValidateListeners.get(propertyName); if (list == null) { list = new ArrayList(); list.add(listener); m_impValidateListeners.put(propertyName, list); } else { list.add(listener); } } /** * Remove Accounting Facts Validation Listener of a table * @param tableName table name * @param listener listener */ public void removeFactsValidate (String tableName, FactsValidator listener) { if (tableName == null || listener == null) return; String propertyName = (listener instanceof ModelValidator && m_globalValidators.contains((ModelValidator)listener)) ? tableName + "*" : tableName + listener.getAD_Client_ID(); ArrayList list = m_factsValidateListeners.get(propertyName); if (list == null) return; list.remove(listener); if (list.size() == 0) m_factsValidateListeners.remove(propertyName); } // removeFactsValidate /** * Fire Accounting Facts Validation event of a table.
    * - Call {@link FactsValidator#factsValidate(MAcctSchema, List, PO)} on register validators.
    * - Fire {@link IEventTopics#ACCT_FACTS_VALIDATE} OSGi event. * @param schema * @param facts * @param po PO instance of event * @return error message or null */ public String fireFactsValidate (MAcctSchema schema, List facts, PO po) { if (schema == null || facts == null || po == null) return null; String propertyName = po.get_TableName() + "*"; ArrayList list = m_factsValidateListeners.get(propertyName); if (list != null) { //ad_entitytype.modelvalidationclasses String error = fireFactsValidate(schema, facts, po, list); if (error != null && error.length() > 0) return error; } propertyName = po.get_TableName() + po.getAD_Client_ID(); list = m_factsValidateListeners.get(propertyName); if (list != null) { //ad_client.modelvalidationclasses String error = fireFactsValidate(schema, facts, po, list); if (error != null && error.length() > 0) return error; } //process osgi event handlers FactsEventData eventData = new FactsEventData(schema, facts, po); Event event = EventManager.newEvent(IEventTopics.ACCT_FACTS_VALIDATE, new EventProperty(EventManager.EVENT_DATA, eventData), new EventProperty(EventManager.TABLE_NAME_PROPERTY, po.get_TableName())); EventManager.getInstance().sendEvent(event); @SuppressWarnings("unchecked") List errors = (List) event.getProperty(IEventManager.EVENT_ERROR_MESSAGES); if (errors != null && !errors.isEmpty()) { Collections.reverse(errors); StringBuilder eventErrors = new StringBuilder(""); for (String error : errors) { eventErrors.append(error).append("
    "); } return eventErrors.toString(); } return null; } // fireFactsValidate /** * Fire Accounting Facts Validation event of a table.
    * - Call {@link FactsValidator#factsValidate(MAcctSchema, List, PO)} on register validators. * @param schema * @param facts * @param po PO instance of event * @param list register validators * @return error message or null */ private String fireFactsValidate(MAcctSchema schema, List facts, PO po, ArrayList list) { for (int i = 0; i < list.size(); i++) { FactsValidator validator = null; try { validator = list.get(i); if (validator.getAD_Client_ID() == po.getAD_Client_ID() || (validator instanceof ModelValidator && m_globalValidators.contains((ModelValidator)validator))) { String error = validator.factsValidate(schema, facts, po); if (error != null && error.length() > 0) { if (log.isLoggable(Level.FINE)) { log.log(Level.FINE, "po="+po+" schema="+schema+" validator="+validator); } return error; } } } catch (Exception e) { //log the stack trace log.log(Level.SEVERE, e.getLocalizedMessage(), e); // Exceptions are errors and should stop the document processing - teo_sarca [ 1679692 ] String error = e.getLocalizedMessage(); if (error == null) error = e.toString(); return error; } } return null; } /** * Fire Import Validation event.
    * - Call {@link ImportValidator#validate(ImportProcess, Object, Object, int)} on registered validators.
    * - Fire IEventTopics.IMPORT_* OSGi event. * @param process import process * @param importModel import record (e.g. X_I_BPartner) * @param targetModel target model (e.g. MBPartner, MBPartnerLocation, MUser) * @param timing see ImportValidator.TIMING_* constants */ public void fireImportValidate (ImportProcess process, PO importModel, PO targetModel, int timing) { String propertyName = process.getImportTableName() + "*"; ArrayList list = m_impValidateListeners.get(propertyName); if (list != null) { for (ImportValidator validator : list) { validator.validate(process, importModel, targetModel, timing); } } //osgi event handler ImportEventData eventData = new ImportEventData(process, importModel, targetModel); String topic = null; if (timing == ImportValidator.TIMING_AFTER_IMPORT) topic = IEventTopics.IMPORT_AFTER_IMPORT; else if (timing == ImportValidator.TIMING_AFTER_VALIDATE) topic = IEventTopics.IMPORT_AFTER_VALIDATE; else if (timing == ImportValidator.TIMING_BEFORE_IMPORT) topic = IEventTopics.IMPORT_BEFORE_IMPORT; else if (timing == ImportValidator.TIMING_BEFORE_VALIDATE) topic = IEventTopics.IMPORT_BEFORE_VALIDATE; Event event = EventManager.newEvent(topic, new EventProperty(EventManager.EVENT_DATA, eventData), new EventProperty(EventManager.IMPORT_TABLE_NAME_PROPERTY, process.getImportTableName())); EventManager.getInstance().sendEvent(event); } /** * String Representation * @return info */ @Override public String toString() { StringBuilder sb = new StringBuilder("ModelValidationEngine["); sb.append("Validators=#").append(m_validators.size()) .append(", ModelChange=#").append(m_modelChangeListeners.size()) .append(", DocValidate=#").append(m_docValidateListeners.size()) .append("]"); return sb.toString(); } // toString /** * Get Model Validation Engine Info * @param sb optional string buffer * @param ctx context * @return Model Validation Engine Info * * author Teo Sarca, FR [ 1724662 ] */ public StringBuffer getInfoDetail(StringBuffer sb, Properties ctx) { if (sb == null) sb = new StringBuffer(); sb.append("=== ModelValidationEngine ===").append(Env.NL); sb.append("Validators #").append(m_validators.size()).append(Env.NL); for (ModelValidator mv : m_validators) { sb.append(mv.toString()).append(Env.NL); } sb.append(Env.NL).append(Env.NL); // sb.append("ModelChange #").append(m_modelChangeListeners.size()).append(Env.NL); Iterator it = m_modelChangeListeners.keySet().iterator(); while(it.hasNext()) { String key = it.next(); ArrayList list = m_modelChangeListeners.get(key); for (ModelValidator mv : list) { sb.append(key).append(": ").append(mv.toString()).append(Env.NL); } } sb.append(Env.NL).append(Env.NL); // sb.append("DocValidate #").append(m_docValidateListeners.size()).append(Env.NL); it = m_docValidateListeners.keySet().iterator(); while(it.hasNext()) { String key = it.next(); ArrayList list = m_docValidateListeners.get(key); for (ModelValidator mv : list) { sb.append(key).append(": ").append(mv.toString()).append(Env.NL); } } sb.append(Env.NL).append(Env.NL); // return sb; } /** * After Load Preferences into Context for selected client.
    * Fire afterLoadPreferences model validator event and {@link IEventTopics#PREF_AFTER_LOAD} OSGi event. * @param ctx context * @see org.compiere.util.Login#loadPreferences(KeyNamePair, KeyNamePair, java.sql.Timestamp, String) * author Teo Sarca - FR [ 1670025 ] - https://sourceforge.net/p/adempiere/feature-requests/78/ */ public void afterLoadPreferences (Properties ctx) { int AD_Client_ID = Env.getAD_Client_ID(ctx); for (int i = 0; i < m_validators.size(); i++) { ModelValidator validator = m_validators.get(i); if (AD_Client_ID == validator.getAD_Client_ID() || m_globalValidators.contains(validator)) { java.lang.reflect.Method m = null; try { m = validator.getClass().getMethod("afterLoadPreferences", new Class[]{Properties.class}); } catch(NoSuchMethodException e) { // ignore } try { if (m != null) m.invoke(validator, ctx); } catch (Exception e) { log.warning("" + validator + ": " + e.getLocalizedMessage()); } } } //osgi event handlers Event event = new Event(IEventTopics.PREF_AFTER_LOAD, (Map)null); EventManager.getInstance().sendEvent(event); } /** * Before Save Properties for selected client. * @deprecated for deprecated swing client only */ @Deprecated public void beforeSaveProperties () { int AD_Client_ID = Env.getAD_Client_ID(Env.getCtx()); for (int i = 0; i < m_validators.size(); i++) { ModelValidator validator = m_validators.get(i); if (AD_Client_ID == validator.getAD_Client_ID() || m_globalValidators.contains(validator)) { java.lang.reflect.Method m = null; try { m = validator.getClass().getMethod("beforeSaveProperties"); } catch(NoSuchMethodException e) { // ignore } try { if (m != null) m.invoke(validator); } catch (Exception e) { log.warning("" + validator + ": " + e.getLocalizedMessage()); } } } } } // ModelValidatorEngine