* Separate the new callout extension interface from the classic callout interface. this is to avoid confusion since the methodName argument is not used here and implementation is expected to implement the start method.

* Change the getCallout method to findCallout and return a list of registered callout for a column. Callout is not a singleton service and developer can register multiple callout per column
* Make consistent with current semantic where callout is not invoke if record is processed and not always updateable.
* Make consistent with current semantic where only non empty string return from the callout instance is return to the caller as an error message string.
This commit is contained in:
Heng Sin Low 2010-03-09 00:27:33 +00:00
parent f73caa3e98
commit 052a829023
5 changed files with 177 additions and 100 deletions

View File

@ -58,7 +58,7 @@ Instead, you specify Table and Column in the extension declaration.
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":org.compiere.model.Callout"/>
<meta.attribute kind="java" basedOn=":org.adempiere.base.IColumnCallout"/>
</appinfo>
</annotation>
</attribute>

View File

@ -29,12 +29,12 @@ public class Core {
};
}
public static Callout getCallout(String tableName, String columnName) {
public static List<IColumnCallout> findCallout(String tableName, String columnName) {
ServiceQuery query = new ServiceQuery();
query.put("tableName", tableName);
query.put("columnName", columnName);
return Service.locate(Callout.class, query);
return Service.list(IColumnCallout.class, query);
}

View File

@ -0,0 +1,48 @@
/******************************************************************************
* 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.adempiere.base;
import java.util.Properties;
import org.compiere.model.GridField;
import org.compiere.model.GridTab;
/**
* Column Callout Interface
*/
public interface IColumnCallout extends IService
{
/**
* Start Callout.
* <p>
* Callout's are used for cross field validation and setting values in other fields
* when returning a non empty (error message) string, an exception is raised
* <p>
* When invoked, the Tab model has the new value!
*
* @param ctx Context
* @param WindowNo current Window No
* @param mTab Model Tab
* @param mField Model Field
* @param value The new value
* @param oldValue The old value
* @return Error message or ""
*/
public String start (Properties ctx, int WindowNo,
GridTab mTab, GridField mField, Object value, Object oldValue);
}

View File

@ -27,7 +27,7 @@ import org.adempiere.base.IService;
* @author Jorg Janke
* @version $Id: Callout.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $
*/
public interface Callout extends IService
public interface Callout
{
/**
* Start Callout.

View File

@ -38,6 +38,7 @@ import javax.script.ScriptEngine;
import javax.swing.event.EventListenerList;
import org.adempiere.base.Core;
import org.adempiere.base.IColumnCallout;
import org.adempiere.base.Service;
import org.compiere.util.CLogMgt;
import org.compiere.util.CLogger;
@ -2684,19 +2685,47 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
*/
public String processCallout (GridField field)
{
//
if (isProcessed() && !field.isAlwaysUpdateable()) // only active records
return ""; // "DocProcessed";
Object value = field.getValue();
Object oldValue = field.getOldValue();
Callout co = Core.getCallout(getTableName(), field.getColumnName());
if (co!=null) {
return co.start(m_vo.ctx, "", m_vo.WindowNo, this, field, value, oldValue);
List<IColumnCallout> callouts = Core.findCallout(getTableName(), field.getColumnName());
if (callouts != null && !callouts.isEmpty()) {
for(IColumnCallout co : callouts)
{
String retValue = "";
String cmd = co.getClass().getName();
//detect infinite loop
if (activeCallouts.contains(cmd)) continue;
try
{
activeCallouts.add(cmd);
retValue = co.start(m_vo.ctx, m_vo.WindowNo, this, field, value, oldValue);
}
catch (Exception e)
{
log.log(Level.SEVERE, "start", e);
retValue = "Callout Invalid: " + e.toString();
return retValue;
}
finally
{
activeCallouts.remove(cmd);
}
if (!Util.isEmpty(retValue)) // interrupt on first error
{
log.severe (retValue);
return retValue;
}
}
}
String callout = field.getCallout();
if (callout.length() == 0)
return "";
//
if (isProcessed() && !field.isAlwaysUpdateable()) // only active records
return ""; // "DocProcessed";
log.fine(field.getColumnName() + "=" + value
+ " (" + callout + ") - old=" + oldValue);