IDEMPIERE-5015 add org.adempiere.base.annotation.Callout annotation (#948)
This commit is contained in:
parent
c43cefd0c9
commit
22c09368e6
|
@ -13,3 +13,4 @@ Export-Package: org.compiere.model
|
||||||
Bundle-ClassPath: .
|
Bundle-ClassPath: .
|
||||||
Automatic-Module-Name: org.adempiere.base.callout
|
Automatic-Module-Name: org.adempiere.base.callout
|
||||||
Bundle-Vendor: iDempiere Community
|
Bundle-Vendor: iDempiere Community
|
||||||
|
Import-Package: org.osgi.service.component.annotations;version="1.3.0"
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.adempiere.base.callout.CostAdjustmentCalloutFactory">
|
|
||||||
<implementation class="org.adempiere.base.callout.CostAdjustmentCalloutFactory"/>
|
|
||||||
<service>
|
|
||||||
<provide interface="org.adempiere.base.IColumnCalloutFactory"/>
|
|
||||||
</service>
|
|
||||||
</scr:component>
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.adempiere.base.callout.factory.AnnotationBasedColumnCalloutFactoryImpl">
|
||||||
|
<service>
|
||||||
|
<provide interface="org.adempiere.base.IColumnCalloutFactory"/>
|
||||||
|
</service>
|
||||||
|
<implementation class="org.adempiere.base.callout.factory.AnnotationBasedColumnCalloutFactoryImpl"/>
|
||||||
|
</scr:component>
|
|
@ -1,5 +1,4 @@
|
||||||
bin.includes = META-INF/,\
|
bin.includes = META-INF/,\
|
||||||
OSGI-INF/costadjustmentcalloutfactory.xml,\
|
|
||||||
OSGI-INF/,\
|
OSGI-INF/,\
|
||||||
.
|
.
|
||||||
output.. = target/classes/
|
output.. = target/classes/
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* Copyright (C) 2013 Diego Ruiz *
|
|
||||||
* Copyright (C) 2013 Trek Global *
|
|
||||||
* 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. *
|
|
||||||
*****************************************************************************/
|
|
||||||
package org.adempiere.base.callout;
|
|
||||||
|
|
||||||
import org.adempiere.base.IColumnCallout;
|
|
||||||
import org.adempiere.base.IColumnCalloutFactory;
|
|
||||||
import org.adempiere.model.CalloutBPartnerQuickEntry;
|
|
||||||
import org.compiere.model.MBPartner;
|
|
||||||
|
|
||||||
public class BPartnerCalloutFactory implements IColumnCalloutFactory {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IColumnCallout[] getColumnCallouts(String tableName, String columnName) {
|
|
||||||
if (tableName.equalsIgnoreCase(MBPartner.Table_Name)) {
|
|
||||||
return new IColumnCallout[]{new CalloutBPartnerQuickEntry()};
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,186 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* Copyright (C) 2013 Heng Sin Low *
|
|
||||||
* Copyright (C) 2013 Trek Global *
|
|
||||||
* 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. *
|
|
||||||
*****************************************************************************/
|
|
||||||
package org.adempiere.base.callout;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.adempiere.base.IColumnCallout;
|
|
||||||
import org.adempiere.base.IColumnCalloutFactory;
|
|
||||||
import org.compiere.model.GridField;
|
|
||||||
import org.compiere.model.GridTab;
|
|
||||||
import org.compiere.model.GridTable;
|
|
||||||
import org.compiere.model.I_M_InventoryLine;
|
|
||||||
import org.compiere.model.MAcctSchema;
|
|
||||||
import org.compiere.model.MClient;
|
|
||||||
import org.compiere.model.MCost;
|
|
||||||
import org.compiere.model.MCostElement;
|
|
||||||
import org.compiere.model.MDocType;
|
|
||||||
import org.compiere.model.MInventory;
|
|
||||||
import org.compiere.model.MProduct;
|
|
||||||
import org.compiere.util.Env;
|
|
||||||
import org.compiere.util.Msg;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author hengsin
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class CostAdjustmentCalloutFactory implements IColumnCalloutFactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public CostAdjustmentCalloutFactory() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.adempiere.base.IColumnCalloutFactory#getColumnCallouts(java.lang.String, java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public IColumnCallout[] getColumnCallouts(String tableName,
|
|
||||||
String columnName) {
|
|
||||||
if (tableName.equalsIgnoreCase(I_M_InventoryLine.Table_Name)) {
|
|
||||||
if (columnName.equalsIgnoreCase(I_M_InventoryLine.COLUMNNAME_M_Product_ID))
|
|
||||||
return new IColumnCallout[]{new CostAdjustmentLineProduct()};
|
|
||||||
else if (columnName.equalsIgnoreCase(I_M_InventoryLine.COLUMNNAME_M_AttributeSetInstance_ID))
|
|
||||||
return new IColumnCallout[]{new CostAdjustmentLineASI()};
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* callout for m_product_id
|
|
||||||
*/
|
|
||||||
private static class CostAdjustmentLineProduct implements IColumnCallout {
|
|
||||||
@Override
|
|
||||||
public String start(Properties ctx, int WindowNo, GridTab mTab,
|
|
||||||
GridField mField, Object value, Object oldValue) {
|
|
||||||
String trxName = null;
|
|
||||||
if ( mTab != null
|
|
||||||
&& mTab.getTableModel() != null) {
|
|
||||||
GridTable gt = mTab.getTableModel();
|
|
||||||
if (gt.isImporting()) {
|
|
||||||
trxName = gt.get_TrxName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MInventory inventory = new MInventory(ctx, (Integer) mTab.getValue("M_Inventory_ID"), trxName);
|
|
||||||
if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(inventory.getC_DocType().getDocSubTypeInv())) {
|
|
||||||
String costingMethod = inventory.getCostingMethod();
|
|
||||||
if (value == null) {
|
|
||||||
mTab.setValue(I_M_InventoryLine.COLUMNNAME_CurrentCostPrice, BigDecimal.ZERO);
|
|
||||||
mTab.setValue(I_M_InventoryLine.COLUMNNAME_NewCostPrice, BigDecimal.ZERO);
|
|
||||||
} else {
|
|
||||||
MProduct product = MProduct.get(ctx, (Integer) value);
|
|
||||||
MClient client = MClient.get(ctx);
|
|
||||||
MAcctSchema as = client.getAcctSchema();
|
|
||||||
|
|
||||||
String costingLevel = product.getCostingLevel(as);
|
|
||||||
if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(costingLevel)) {
|
|
||||||
mTab.setValue(I_M_InventoryLine.COLUMNNAME_CurrentCostPrice, BigDecimal.ZERO);
|
|
||||||
mTab.setValue(I_M_InventoryLine.COLUMNNAME_NewCostPrice, BigDecimal.ZERO);
|
|
||||||
}else {
|
|
||||||
Object asiValue = mTab.getValue(I_M_InventoryLine.COLUMNNAME_M_AttributeSetInstance_ID);
|
|
||||||
int M_ASI_ID = asiValue != null ? (Integer)asiValue : 0;
|
|
||||||
int AD_Org_ID = inventory.getAD_Org_ID();
|
|
||||||
int C_Currency_ID = inventory.getC_Currency_ID();
|
|
||||||
|
|
||||||
if (as.getC_Currency_ID() != C_Currency_ID)
|
|
||||||
{
|
|
||||||
MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(ctx, client.get_ID());
|
|
||||||
for (int i = 0; i < ass.length ; i ++)
|
|
||||||
{
|
|
||||||
MAcctSchema a = ass[i];
|
|
||||||
if (a.getC_Currency_ID() == C_Currency_ID)
|
|
||||||
as = a ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MCost cost = product.getCostingRecord(as, AD_Org_ID, M_ASI_ID, costingMethod);
|
|
||||||
if (cost == null) {
|
|
||||||
if (!MCostElement.COSTINGMETHOD_StandardCosting.equals(costingMethod)) {
|
|
||||||
mTab.setValue(mField, null);
|
|
||||||
return Msg.getMsg(Env.getCtx(), "NoCostingRecord");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mTab.setValue(I_M_InventoryLine.COLUMNNAME_CurrentCostPrice, cost.getCurrentCostPrice());
|
|
||||||
mTab.setValue(I_M_InventoryLine.COLUMNNAME_NewCostPrice, cost.getCurrentCostPrice());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* callout for m_attributesetinstance_id
|
|
||||||
*/
|
|
||||||
private class CostAdjustmentLineASI implements IColumnCallout {
|
|
||||||
@Override
|
|
||||||
public String start(Properties ctx, int WindowNo, GridTab mTab,
|
|
||||||
GridField mField, Object value, Object oldValue) {
|
|
||||||
String trxName = null;
|
|
||||||
if ( mTab != null
|
|
||||||
&& mTab.getTableModel() != null) {
|
|
||||||
GridTable gt = mTab.getTableModel();
|
|
||||||
if (gt.isImporting()) {
|
|
||||||
trxName = gt.get_TrxName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MInventory inventory = new MInventory(ctx, (Integer) mTab.getValue("M_Inventory_ID"), trxName);
|
|
||||||
if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(inventory.getC_DocType().getDocSubTypeInv())) {
|
|
||||||
String costingMethod = inventory.getCostingMethod();
|
|
||||||
Object productValue = mTab.getValue(I_M_InventoryLine.COLUMNNAME_M_Product_ID);
|
|
||||||
if (productValue == null || ((Integer)productValue).intValue() == 0) return null;
|
|
||||||
|
|
||||||
MProduct product = MProduct.get(ctx, (Integer)productValue);
|
|
||||||
int M_ASI_ID = value != null ? (Integer)value : 0;
|
|
||||||
int AD_Org_ID = inventory.getAD_Org_ID();
|
|
||||||
int C_Currency_ID = inventory.getC_Currency_ID();
|
|
||||||
|
|
||||||
MClient client = MClient.get(ctx);
|
|
||||||
MAcctSchema as = client.getAcctSchema();
|
|
||||||
|
|
||||||
if (as.getC_Currency_ID() != C_Currency_ID)
|
|
||||||
{
|
|
||||||
MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(ctx, client.get_ID());
|
|
||||||
for (int i = 0; i < ass.length ; i ++)
|
|
||||||
{
|
|
||||||
MAcctSchema a = ass[i];
|
|
||||||
if (a.getC_Currency_ID() == C_Currency_ID)
|
|
||||||
as = a ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MCost cost = product.getCostingRecord(as, AD_Org_ID, M_ASI_ID, costingMethod);
|
|
||||||
if (cost == null) {
|
|
||||||
if (!MCostElement.COSTINGMETHOD_StandardCosting.equals(costingMethod)) {
|
|
||||||
mTab.setValue(mField, null);
|
|
||||||
return Msg.getMsg(Env.getCtx(), "NoCostingRecord");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cost != null) {
|
|
||||||
BigDecimal currentCost = (BigDecimal) mTab.getValue(I_M_InventoryLine.COLUMNNAME_CurrentCostPrice);
|
|
||||||
if (currentCost == null || currentCost.compareTo(cost.getCurrentCostPrice())==0) return null;
|
|
||||||
|
|
||||||
mTab.setValue(I_M_InventoryLine.COLUMNNAME_CurrentCostPrice, cost.getCurrentCostPrice());
|
|
||||||
mTab.setValue(I_M_InventoryLine.COLUMNNAME_NewCostPrice, cost.getCurrentCostPrice());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.adempiere.base.callout;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.adempiere.base.IColumnCallout;
|
||||||
|
import org.adempiere.base.annotation.Callout;
|
||||||
|
import org.compiere.model.GridField;
|
||||||
|
import org.compiere.model.GridTab;
|
||||||
|
import org.compiere.model.GridTable;
|
||||||
|
import org.compiere.model.I_M_InventoryLine;
|
||||||
|
import org.compiere.model.MAcctSchema;
|
||||||
|
import org.compiere.model.MClient;
|
||||||
|
import org.compiere.model.MCost;
|
||||||
|
import org.compiere.model.MCostElement;
|
||||||
|
import org.compiere.model.MDocType;
|
||||||
|
import org.compiere.model.MInventory;
|
||||||
|
import org.compiere.model.MProduct;
|
||||||
|
import org.compiere.util.Env;
|
||||||
|
import org.compiere.util.Msg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Callout(tableName = I_M_InventoryLine.Table_Name, columnName = I_M_InventoryLine.COLUMNNAME_M_AttributeSetInstance_ID)
|
||||||
|
public class CostAdjustmentLineASI implements IColumnCallout {
|
||||||
|
@Override
|
||||||
|
public String start(Properties ctx, int WindowNo, GridTab mTab,
|
||||||
|
GridField mField, Object value, Object oldValue) {
|
||||||
|
String trxName = null;
|
||||||
|
if ( mTab != null
|
||||||
|
&& mTab.getTableModel() != null) {
|
||||||
|
GridTable gt = mTab.getTableModel();
|
||||||
|
if (gt.isImporting()) {
|
||||||
|
trxName = gt.get_TrxName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MInventory inventory = new MInventory(ctx, (Integer) mTab.getValue("M_Inventory_ID"), trxName);
|
||||||
|
if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(inventory.getC_DocType().getDocSubTypeInv())) {
|
||||||
|
String costingMethod = inventory.getCostingMethod();
|
||||||
|
Object productValue = mTab.getValue(I_M_InventoryLine.COLUMNNAME_M_Product_ID);
|
||||||
|
if (productValue == null || ((Integer)productValue).intValue() == 0) return null;
|
||||||
|
|
||||||
|
MProduct product = MProduct.get(ctx, (Integer)productValue);
|
||||||
|
int M_ASI_ID = value != null ? (Integer)value : 0;
|
||||||
|
int AD_Org_ID = inventory.getAD_Org_ID();
|
||||||
|
int C_Currency_ID = inventory.getC_Currency_ID();
|
||||||
|
|
||||||
|
MClient client = MClient.get(ctx);
|
||||||
|
MAcctSchema as = client.getAcctSchema();
|
||||||
|
|
||||||
|
if (as.getC_Currency_ID() != C_Currency_ID)
|
||||||
|
{
|
||||||
|
MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(ctx, client.get_ID());
|
||||||
|
for (int i = 0; i < ass.length ; i ++)
|
||||||
|
{
|
||||||
|
MAcctSchema a = ass[i];
|
||||||
|
if (a.getC_Currency_ID() == C_Currency_ID)
|
||||||
|
as = a ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MCost cost = product.getCostingRecord(as, AD_Org_ID, M_ASI_ID, costingMethod);
|
||||||
|
if (cost == null) {
|
||||||
|
if (!MCostElement.COSTINGMETHOD_StandardCosting.equals(costingMethod)) {
|
||||||
|
mTab.setValue(mField, null);
|
||||||
|
return Msg.getMsg(Env.getCtx(), "NoCostingRecord");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cost != null) {
|
||||||
|
BigDecimal currentCost = (BigDecimal) mTab.getValue(I_M_InventoryLine.COLUMNNAME_CurrentCostPrice);
|
||||||
|
if (currentCost == null || currentCost.compareTo(cost.getCurrentCostPrice())==0) return null;
|
||||||
|
|
||||||
|
mTab.setValue(I_M_InventoryLine.COLUMNNAME_CurrentCostPrice, cost.getCurrentCostPrice());
|
||||||
|
mTab.setValue(I_M_InventoryLine.COLUMNNAME_NewCostPrice, cost.getCurrentCostPrice());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.adempiere.base.callout;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.adempiere.base.IColumnCallout;
|
||||||
|
import org.adempiere.base.annotation.Callout;
|
||||||
|
import org.compiere.model.GridField;
|
||||||
|
import org.compiere.model.GridTab;
|
||||||
|
import org.compiere.model.GridTable;
|
||||||
|
import org.compiere.model.I_M_InventoryLine;
|
||||||
|
import org.compiere.model.MAcctSchema;
|
||||||
|
import org.compiere.model.MClient;
|
||||||
|
import org.compiere.model.MCost;
|
||||||
|
import org.compiere.model.MCostElement;
|
||||||
|
import org.compiere.model.MDocType;
|
||||||
|
import org.compiere.model.MInventory;
|
||||||
|
import org.compiere.model.MProduct;
|
||||||
|
import org.compiere.util.Env;
|
||||||
|
import org.compiere.util.Msg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Callout(tableName = I_M_InventoryLine.Table_Name, columnName = I_M_InventoryLine.COLUMNNAME_M_Product_ID)
|
||||||
|
public class CostAdjustmentLineProduct implements IColumnCallout {
|
||||||
|
@Override
|
||||||
|
public String start(Properties ctx, int WindowNo, GridTab mTab,
|
||||||
|
GridField mField, Object value, Object oldValue) {
|
||||||
|
String trxName = null;
|
||||||
|
if ( mTab != null
|
||||||
|
&& mTab.getTableModel() != null) {
|
||||||
|
GridTable gt = mTab.getTableModel();
|
||||||
|
if (gt.isImporting()) {
|
||||||
|
trxName = gt.get_TrxName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MInventory inventory = new MInventory(ctx, (Integer) mTab.getValue("M_Inventory_ID"), trxName);
|
||||||
|
if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(inventory.getC_DocType().getDocSubTypeInv())) {
|
||||||
|
String costingMethod = inventory.getCostingMethod();
|
||||||
|
if (value == null) {
|
||||||
|
mTab.setValue(I_M_InventoryLine.COLUMNNAME_CurrentCostPrice, BigDecimal.ZERO);
|
||||||
|
mTab.setValue(I_M_InventoryLine.COLUMNNAME_NewCostPrice, BigDecimal.ZERO);
|
||||||
|
} else {
|
||||||
|
MProduct product = MProduct.get(ctx, (Integer) value);
|
||||||
|
MClient client = MClient.get(ctx);
|
||||||
|
MAcctSchema as = client.getAcctSchema();
|
||||||
|
|
||||||
|
String costingLevel = product.getCostingLevel(as);
|
||||||
|
if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(costingLevel)) {
|
||||||
|
mTab.setValue(I_M_InventoryLine.COLUMNNAME_CurrentCostPrice, BigDecimal.ZERO);
|
||||||
|
mTab.setValue(I_M_InventoryLine.COLUMNNAME_NewCostPrice, BigDecimal.ZERO);
|
||||||
|
}else {
|
||||||
|
Object asiValue = mTab.getValue(I_M_InventoryLine.COLUMNNAME_M_AttributeSetInstance_ID);
|
||||||
|
int M_ASI_ID = asiValue != null ? (Integer)asiValue : 0;
|
||||||
|
int AD_Org_ID = inventory.getAD_Org_ID();
|
||||||
|
int C_Currency_ID = inventory.getC_Currency_ID();
|
||||||
|
|
||||||
|
if (as.getC_Currency_ID() != C_Currency_ID)
|
||||||
|
{
|
||||||
|
MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(ctx, client.get_ID());
|
||||||
|
for (int i = 0; i < ass.length ; i ++)
|
||||||
|
{
|
||||||
|
MAcctSchema a = ass[i];
|
||||||
|
if (a.getC_Currency_ID() == C_Currency_ID)
|
||||||
|
as = a ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MCost cost = product.getCostingRecord(as, AD_Org_ID, M_ASI_ID, costingMethod);
|
||||||
|
if (cost == null) {
|
||||||
|
if (!MCostElement.COSTINGMETHOD_StandardCosting.equals(costingMethod)) {
|
||||||
|
mTab.setValue(mField, null);
|
||||||
|
return Msg.getMsg(Env.getCtx(), "NoCostingRecord");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mTab.setValue(I_M_InventoryLine.COLUMNNAME_CurrentCostPrice, cost.getCurrentCostPrice());
|
||||||
|
mTab.setValue(I_M_InventoryLine.COLUMNNAME_NewCostPrice, cost.getCurrentCostPrice());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.adempiere.base.callout.factory;
|
||||||
|
|
||||||
|
import org.adempiere.base.AnnotationBasedColumnCalloutFactory;
|
||||||
|
import org.adempiere.base.IColumnCalloutFactory;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component(immediate = true, service = IColumnCalloutFactory.class)
|
||||||
|
public class AnnotationBasedColumnCalloutFactoryImpl extends AnnotationBasedColumnCalloutFactory {
|
||||||
|
|
||||||
|
public AnnotationBasedColumnCalloutFactoryImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getPackages() {
|
||||||
|
return new String[] {"org.adempiere.base.callout","org.adempiere.model"};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,12 +16,14 @@ package org.adempiere.model;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.adempiere.base.IColumnCallout;
|
import org.adempiere.base.IColumnCallout;
|
||||||
|
import org.adempiere.base.annotation.Callout;
|
||||||
import org.compiere.model.GridField;
|
import org.compiere.model.GridField;
|
||||||
import org.compiere.model.GridTab;
|
import org.compiere.model.GridTab;
|
||||||
import org.compiere.model.MBPartner;
|
import org.compiere.model.MBPartner;
|
||||||
import org.compiere.util.Env;
|
import org.compiere.util.Env;
|
||||||
import org.compiere.util.Util;
|
import org.compiere.util.Util;
|
||||||
|
|
||||||
|
@Callout(tableName = MBPartner.Table_Name, columnName = "*")
|
||||||
public class CalloutBPartnerQuickEntry implements IColumnCallout {
|
public class CalloutBPartnerQuickEntry implements IColumnCallout {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.adempiere.base.callout.BPartnerCalloutFactory">
|
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.adempiere.base.DefaultAnnotationBasedColumnCalloutFactory">
|
||||||
<implementation class="org.adempiere.base.callout.BPartnerCalloutFactory"/>
|
|
||||||
<service>
|
<service>
|
||||||
<provide interface="org.adempiere.base.IColumnCalloutFactory"/>
|
<provide interface="org.adempiere.base.IColumnCalloutFactory"/>
|
||||||
</service>
|
</service>
|
||||||
</scr:component>
|
<implementation class="org.adempiere.base.DefaultAnnotationBasedColumnCalloutFactory"/>
|
||||||
|
</scr:component>
|
|
@ -64,36 +64,6 @@
|
||||||
</run>
|
</run>
|
||||||
</application>
|
</application>
|
||||||
</extension>
|
</extension>
|
||||||
<extension
|
|
||||||
id="org.adempiere.model.CalloutInfoWindow.element"
|
|
||||||
point="org.adempiere.base.IColumnCallout">
|
|
||||||
<callout
|
|
||||||
class="org.adempiere.model.CalloutInfoWindow"
|
|
||||||
columnName="AD_Element_ID"
|
|
||||||
priority="0"
|
|
||||||
tableName="AD_InfoColumn">
|
|
||||||
</callout>
|
|
||||||
</extension>
|
|
||||||
<extension
|
|
||||||
id="org.adempiere.model.CalloutInfoWindow.table"
|
|
||||||
point="org.adempiere.base.IColumnCallout">
|
|
||||||
<callout
|
|
||||||
class="org.adempiere.model.CalloutInfoWindow"
|
|
||||||
columnName="AD_Table_ID"
|
|
||||||
priority="0"
|
|
||||||
tableName="AD_InfoWindow">
|
|
||||||
</callout>
|
|
||||||
</extension>
|
|
||||||
<extension
|
|
||||||
id="org.adempiere.model.CalloutInfoWindow.reference"
|
|
||||||
point="org.adempiere.base.IColumnCallout">
|
|
||||||
<callout
|
|
||||||
class="org.adempiere.model.CalloutInfoWindow"
|
|
||||||
columnName="AD_Reference_ID"
|
|
||||||
priority="0"
|
|
||||||
tableName="AD_InfoColumn">
|
|
||||||
</callout>
|
|
||||||
</extension>
|
|
||||||
<extension
|
<extension
|
||||||
id="org.compiere.model.StandardTaxProvider"
|
id="org.compiere.model.StandardTaxProvider"
|
||||||
name="Standard Tax Provider"
|
name="Standard Tax Provider"
|
||||||
|
|
|
@ -0,0 +1,251 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.adempiere.base;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.base.annotation.Callout;
|
||||||
|
import org.adempiere.base.annotation.Callouts;
|
||||||
|
import org.compiere.util.CLogger;
|
||||||
|
import org.osgi.framework.BundleContext;
|
||||||
|
import org.osgi.framework.wiring.BundleWiring;
|
||||||
|
import org.osgi.service.component.ComponentContext;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
|
|
||||||
|
import io.github.classgraph.AnnotationInfo;
|
||||||
|
import io.github.classgraph.AnnotationInfoList;
|
||||||
|
import io.github.classgraph.ClassGraph;
|
||||||
|
import io.github.classgraph.ClassInfo;
|
||||||
|
import io.github.classgraph.ScanResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class AnnotationBasedColumnCalloutFactory implements IColumnCalloutFactory {
|
||||||
|
|
||||||
|
private final static CLogger s_log = CLogger.getCLogger(AnnotationBasedColumnCalloutFactory.class);
|
||||||
|
|
||||||
|
private BundleContext bundleContext;
|
||||||
|
|
||||||
|
private final Map<String, Map<String, List<String>>> tableNameMap = new HashMap<>();
|
||||||
|
|
||||||
|
private final Map<String, Constructor<?>[]> constructorCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
public AnnotationBasedColumnCalloutFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IColumnCallout[] getColumnCallouts(String tableName, String columnName) {
|
||||||
|
List<IColumnCallout> callouts = new ArrayList<IColumnCallout>();
|
||||||
|
ClassLoader classLoader = bundleContext.getBundle().adapt(BundleWiring.class).getClassLoader();
|
||||||
|
Map<String, List<String>> columnNameMap = tableNameMap.get(tableName);
|
||||||
|
if (columnNameMap != null) {
|
||||||
|
List<String> calloutClassNames = columnNameMap.get(columnName);
|
||||||
|
if (calloutClassNames != null) {
|
||||||
|
newCalloutInstance(callouts, classLoader, calloutClassNames);
|
||||||
|
}
|
||||||
|
calloutClassNames = columnNameMap.get("*");
|
||||||
|
if (calloutClassNames != null) {
|
||||||
|
newCalloutInstance(callouts, classLoader, calloutClassNames);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
columnNameMap = tableNameMap.get("*");
|
||||||
|
if (columnNameMap != null) {
|
||||||
|
List<String> calloutClassNames = columnNameMap.get(columnName);
|
||||||
|
if (calloutClassNames != null) {
|
||||||
|
newCalloutInstance(callouts, classLoader, calloutClassNames);
|
||||||
|
}
|
||||||
|
calloutClassNames = columnNameMap.get("*");
|
||||||
|
if (calloutClassNames != null) {
|
||||||
|
newCalloutInstance(callouts, classLoader, calloutClassNames);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return callouts.toArray(new IColumnCallout[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void newCalloutInstance(List<IColumnCallout> callouts, ClassLoader classLoader,
|
||||||
|
List<String> calloutClassNames) {
|
||||||
|
for(String calloutClass : calloutClassNames) {
|
||||||
|
Constructor<?>[] constructors = constructorCache.get(calloutClass);
|
||||||
|
if (constructors == null) {
|
||||||
|
try {
|
||||||
|
Class<?> clazz = classLoader.loadClass(calloutClass);
|
||||||
|
Constructor<?> constructor = clazz.getDeclaredConstructor();
|
||||||
|
IColumnCallout columnCallout = (IColumnCallout) constructor.newInstance();
|
||||||
|
callouts.add(columnCallout);
|
||||||
|
constructors = new Constructor<?>[] {constructor};
|
||||||
|
constructorCache.put(calloutClass, constructors);
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_log.log(Level.WARNING, e.getMessage(), e);
|
||||||
|
constructors = new Constructor<?>[0];
|
||||||
|
constructorCache.put(calloutClass, constructors);
|
||||||
|
}
|
||||||
|
} else if (constructors.length == 1){
|
||||||
|
try {
|
||||||
|
IColumnCallout columnCallout = (IColumnCallout) constructors[0].newInstance();
|
||||||
|
callouts.add(columnCallout);
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_log.log(Level.WARNING, e.getMessage(), e);
|
||||||
|
constructors = new Constructor<?>[0];
|
||||||
|
constructorCache.put(calloutClass, constructors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses must override this method in order to provide packages to
|
||||||
|
* scan, discover and register {@link IColumnCallout} classes
|
||||||
|
* @return array of packages to be accepted during class scanning
|
||||||
|
* @see ClassGraph#acceptPackagesNonRecursive(String...)
|
||||||
|
*/
|
||||||
|
protected abstract String[] getPackages();
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public void activate(ComponentContext context) throws ClassNotFoundException {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
bundleContext = context.getBundleContext();
|
||||||
|
ClassLoader classLoader = bundleContext.getBundle().adapt(BundleWiring.class).getClassLoader();
|
||||||
|
|
||||||
|
ClassGraph graph = new ClassGraph()
|
||||||
|
.enableAnnotationInfo()
|
||||||
|
.overrideClassLoaders(classLoader)
|
||||||
|
.disableNestedJarScanning()
|
||||||
|
.disableModuleScanning()
|
||||||
|
.acceptPackagesNonRecursive(getPackages());
|
||||||
|
|
||||||
|
try (ScanResult scanResult = graph.scan()) {
|
||||||
|
List<String> processed = new ArrayList<String>();
|
||||||
|
for (ClassInfo classInfo : scanResult.getClassesWithAnnotation(Callouts.class)) {
|
||||||
|
if (classInfo.isAbstract())
|
||||||
|
continue;
|
||||||
|
String className = classInfo.getName();
|
||||||
|
AnnotationInfoList annotationInfos = classInfo.getAnnotationInfoRepeatable(Callout.class);
|
||||||
|
for(AnnotationInfo annotationInfo : annotationInfos) {
|
||||||
|
processAnnotation(className, annotationInfo);
|
||||||
|
}
|
||||||
|
processed.add(className);
|
||||||
|
}
|
||||||
|
for (ClassInfo classInfo : scanResult.getClassesWithAnnotation(Callout.class)) {
|
||||||
|
if (classInfo.isAbstract())
|
||||||
|
continue;
|
||||||
|
String className = classInfo.getName();
|
||||||
|
if (processed.contains(className))
|
||||||
|
continue;
|
||||||
|
AnnotationInfo annotationInfo = classInfo.getAnnotationInfo(Callout.class);
|
||||||
|
processAnnotation(className, annotationInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
long end = System.currentTimeMillis();
|
||||||
|
if (s_log.isLoggable(Level.INFO))
|
||||||
|
s_log.info(this.getClass().getSimpleName() + " loaded "+tableNameMap.size() +" classes in "
|
||||||
|
+((end-start)/1000f) + "s");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processAnnotation(String className, AnnotationInfo annotationInfo) {
|
||||||
|
//not sure why but sometime ClassGraph return Object[] instead of the expected String[]
|
||||||
|
Object[] tableNames = (Object[]) annotationInfo.getParameterValues().getValue("tableName");
|
||||||
|
Object[] columnNames = (Object[]) annotationInfo.getParameterValues().getValue("columnName");
|
||||||
|
|
||||||
|
boolean matchAllTables = false;
|
||||||
|
for(Object tableName : tableNames) {
|
||||||
|
if ("*".equals(tableName) ) {
|
||||||
|
matchAllTables = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean matchAllColumns = false;
|
||||||
|
for(Object columnName : columnNames) {
|
||||||
|
if ("*".equals(columnName)) {
|
||||||
|
matchAllColumns = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//not allow to match everything
|
||||||
|
if (matchAllColumns && matchAllTables)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Map<String, List<String>> columnNameMap = null;
|
||||||
|
if (matchAllTables) {
|
||||||
|
columnNameMap = tableNameMap.get("*");
|
||||||
|
if (columnNameMap == null) {
|
||||||
|
columnNameMap = new HashMap<String, List<String>>();
|
||||||
|
tableNameMap.put("*", columnNameMap);
|
||||||
|
}
|
||||||
|
if (matchAllColumns) {
|
||||||
|
addCallout(className, columnNameMap);
|
||||||
|
} else {
|
||||||
|
addCallout(className, columnNames, columnNameMap);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(Object tableName : tableNames) {
|
||||||
|
columnNameMap = tableNameMap.get(tableName);
|
||||||
|
if (columnNameMap == null) {
|
||||||
|
columnNameMap = new HashMap<String, List<String>>();
|
||||||
|
tableNameMap.put((String)tableName, columnNameMap);
|
||||||
|
}
|
||||||
|
if (matchAllColumns) {
|
||||||
|
addCallout(className, columnNameMap);
|
||||||
|
} else {
|
||||||
|
addCallout(className, columnNames, columnNameMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addCallout(String className, Object[] columnNames, Map<String, List<String>> columnNameMap) {
|
||||||
|
for (Object columnName : columnNames) {
|
||||||
|
List<String> callouts = columnNameMap.get(columnName);
|
||||||
|
if (callouts == null ) {
|
||||||
|
callouts = new ArrayList<String>();
|
||||||
|
columnNameMap.put((String)columnName, callouts);
|
||||||
|
}
|
||||||
|
callouts.add(className);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addCallout(String className, Map<String, List<String>> columnNameMap) {
|
||||||
|
List<String> callouts = columnNameMap.get("*");
|
||||||
|
if (callouts == null ) {
|
||||||
|
callouts = new ArrayList<String>();
|
||||||
|
columnNameMap.put("*", callouts);
|
||||||
|
}
|
||||||
|
callouts.add(className);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.adempiere.base;
|
||||||
|
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component(immediate = true, service = IColumnCalloutFactory.class)
|
||||||
|
public class DefaultAnnotationBasedColumnCalloutFactory extends AnnotationBasedColumnCalloutFactory {
|
||||||
|
|
||||||
|
public DefaultAnnotationBasedColumnCalloutFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getPackages() {
|
||||||
|
return new String[] {"org.adempiere.model"};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -26,6 +26,8 @@ package org.adempiere.base;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.osgi.framework.BundleContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author hengsin
|
* @author hengsin
|
||||||
|
@ -49,4 +51,10 @@ public interface IMappedColumnCalloutFactory {
|
||||||
*/
|
*/
|
||||||
public void removeMapping(String tableName, String columnName, Supplier<IColumnCallout> supplier);
|
public void removeMapping(String tableName, String columnName, Supplier<IColumnCallout> supplier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* scan, discover and register classes with Callout annotation
|
||||||
|
* @param context
|
||||||
|
* @param packages
|
||||||
|
*/
|
||||||
|
public void scan(BundleContext context, String... packages);
|
||||||
}
|
}
|
|
@ -24,13 +24,26 @@
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
package org.adempiere.base;
|
package org.adempiere.base;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.base.annotation.Callout;
|
||||||
|
import org.adempiere.base.annotation.Callouts;
|
||||||
|
import org.compiere.util.CLogger;
|
||||||
|
import org.osgi.framework.BundleContext;
|
||||||
|
import org.osgi.framework.wiring.BundleWiring;
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
|
||||||
|
import io.github.classgraph.AnnotationInfo;
|
||||||
|
import io.github.classgraph.AnnotationInfoList;
|
||||||
|
import io.github.classgraph.ClassGraph;
|
||||||
|
import io.github.classgraph.ClassInfo;
|
||||||
|
import io.github.classgraph.ScanResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author hengsin
|
* @author hengsin
|
||||||
|
@ -42,6 +55,8 @@ import org.osgi.service.component.annotations.Component;
|
||||||
property = {"service.ranking:Integer=1"})
|
property = {"service.ranking:Integer=1"})
|
||||||
public class MappedColumnCalloutFactory implements IColumnCalloutFactory, IMappedColumnCalloutFactory {
|
public class MappedColumnCalloutFactory implements IColumnCalloutFactory, IMappedColumnCalloutFactory {
|
||||||
|
|
||||||
|
private final static CLogger s_log = CLogger.getCLogger(MappedColumnCalloutFactory.class);
|
||||||
|
|
||||||
private final HashMap<String, List<Supplier<IColumnCallout>>> calloutMap = new HashMap<>();
|
private final HashMap<String, List<Supplier<IColumnCallout>>> calloutMap = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,4 +116,114 @@ public class MappedColumnCalloutFactory implements IColumnCalloutFactory, IMappe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scan(BundleContext context, String... packages) {
|
||||||
|
ClassLoader classLoader = context.getBundle().adapt(BundleWiring.class).getClassLoader();
|
||||||
|
|
||||||
|
ClassGraph graph = new ClassGraph()
|
||||||
|
.enableAnnotationInfo()
|
||||||
|
.overrideClassLoaders(classLoader)
|
||||||
|
.disableNestedJarScanning()
|
||||||
|
.disableModuleScanning()
|
||||||
|
.acceptPackagesNonRecursive(packages);
|
||||||
|
|
||||||
|
try (ScanResult scanResult = graph.scan()) {
|
||||||
|
List<String> processed = new ArrayList<String>();
|
||||||
|
for (ClassInfo classInfo : scanResult.getClassesWithAnnotation(Callouts.class)) {
|
||||||
|
if (classInfo.isAbstract())
|
||||||
|
continue;
|
||||||
|
String className = classInfo.getName();
|
||||||
|
AnnotationInfoList annotationInfos = classInfo.getAnnotationInfoRepeatable(Callout.class);
|
||||||
|
for(AnnotationInfo annotationInfo : annotationInfos) {
|
||||||
|
processAnnotation(className, annotationInfo, classLoader);
|
||||||
|
}
|
||||||
|
processed.add(className);
|
||||||
|
}
|
||||||
|
for (ClassInfo classInfo : scanResult.getClassesWithAnnotation(Callout.class)) {
|
||||||
|
if (classInfo.isAbstract())
|
||||||
|
continue;
|
||||||
|
String className = classInfo.getName();
|
||||||
|
if (processed.contains(className))
|
||||||
|
continue;
|
||||||
|
AnnotationInfo annotationInfo = classInfo.getAnnotationInfo(Callout.class);
|
||||||
|
processAnnotation(className, annotationInfo, classLoader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processAnnotation(String className, AnnotationInfo annotationInfo, ClassLoader classLoader) {
|
||||||
|
Object[] tableNames = (Object[]) annotationInfo.getParameterValues().getValue("tableName");
|
||||||
|
Object[] columnNames = (Object[]) annotationInfo.getParameterValues().getValue("columnName");
|
||||||
|
|
||||||
|
boolean matchAllTables = false;
|
||||||
|
for(Object tableName : tableNames) {
|
||||||
|
if ("*".equals(tableName) ) {
|
||||||
|
matchAllTables = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean matchAllColumns = false;
|
||||||
|
for(Object columnName : columnNames) {
|
||||||
|
if ("*".equals(columnName)) {
|
||||||
|
matchAllColumns = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//not allow to match everything
|
||||||
|
if (matchAllColumns && matchAllTables)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class<?> clazz = classLoader.loadClass(className);
|
||||||
|
Constructor<?> constructor = clazz.getDeclaredConstructor();
|
||||||
|
CalloutSupplier supplier = new CalloutSupplier(constructor);
|
||||||
|
if (matchAllTables) {
|
||||||
|
for(Object columnName : columnNames) {
|
||||||
|
addMapping("*", (String)columnName, supplier);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(Object tableName : tableNames) {
|
||||||
|
if (matchAllColumns) {
|
||||||
|
addMapping((String)tableName, "*", supplier);
|
||||||
|
} else {
|
||||||
|
for(Object columnName : columnNames) {
|
||||||
|
addMapping((String)tableName, (String)columnName, supplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (s_log.isLoggable(Level.INFO))
|
||||||
|
s_log.log(Level.INFO, e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CalloutSupplier implements Supplier<IColumnCallout> {
|
||||||
|
|
||||||
|
private Constructor<?> constructor;
|
||||||
|
|
||||||
|
private CalloutSupplier(Constructor<?> constructor) {
|
||||||
|
this.constructor = constructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IColumnCallout get() {
|
||||||
|
IColumnCallout callout = null;
|
||||||
|
if (constructor != null) {
|
||||||
|
try {
|
||||||
|
callout = (IColumnCallout) constructor.newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
constructor = null;
|
||||||
|
s_log.log(Level.WARNING, e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return callout;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.adempiere.base.annotation;
|
||||||
|
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Repeatable;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for Column Callout. This should only be used with class that implements the IColumnCallout interface.
|
||||||
|
* You can repeat the annotation multiple time for different table and column name combination
|
||||||
|
* Note that you can't use * for both tableName and columnName attribute.
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Repeatable(Callouts.class)
|
||||||
|
public @interface Callout {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return table names or * to match all tables
|
||||||
|
*/
|
||||||
|
String[] tableName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return column names or * to match all columns
|
||||||
|
*/
|
||||||
|
String[] columnName();
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.adempiere.base.annotation;
|
||||||
|
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
public @interface Callouts {
|
||||||
|
Callout[] value() default {};
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.adempiere.base.IColumnCallout;
|
import org.adempiere.base.IColumnCallout;
|
||||||
|
import org.adempiere.base.annotation.Callout;
|
||||||
import org.compiere.model.AccessSqlParser;
|
import org.compiere.model.AccessSqlParser;
|
||||||
import org.compiere.model.AccessSqlParser.TableInfo;
|
import org.compiere.model.AccessSqlParser.TableInfo;
|
||||||
import org.compiere.model.GridField;
|
import org.compiere.model.GridField;
|
||||||
|
@ -35,6 +36,8 @@ import org.compiere.util.Env;
|
||||||
* @author hengsin
|
* @author hengsin
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@Callout(tableName = "AD_InfoWindow", columnName = "AD_Table_ID")
|
||||||
|
@Callout(tableName = "AD_InfoColumn", columnName = {"AD_Element_ID","AD_Reference_ID"})
|
||||||
public class CalloutInfoWindow implements IColumnCallout {
|
public class CalloutInfoWindow implements IColumnCallout {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,188 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.idempiere.test.model;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
import org.adempiere.base.ColumnCalloutManager;
|
||||||
|
import org.adempiere.base.Core;
|
||||||
|
import org.adempiere.base.IColumnCallout;
|
||||||
|
import org.adempiere.model.CalloutInfoWindow;
|
||||||
|
import org.compiere.Adempiere;
|
||||||
|
import org.compiere.model.Callout;
|
||||||
|
import org.compiere.model.I_M_InventoryLine;
|
||||||
|
import org.compiere.model.MBPartner;
|
||||||
|
import org.compiere.model.MColumn;
|
||||||
|
import org.compiere.model.MRule;
|
||||||
|
import org.compiere.model.Query;
|
||||||
|
import org.compiere.util.Env;
|
||||||
|
import org.idempiere.test.AbstractTestCase;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CalloutTest extends AbstractTestCase {
|
||||||
|
|
||||||
|
public CalloutTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAnnotatedCallout() {
|
||||||
|
List<IColumnCallout> callouts = ColumnCalloutManager.findCallout("AD_InfoWindow", "AD_Table_ID");
|
||||||
|
assertNotNull(callouts, "Null column callouts for AD_InfoWindow.AD_Table_ID");
|
||||||
|
assertTrue(callouts.size() > 0, "Empty column callouts for AD_InfoWindow.AD_Table_ID");
|
||||||
|
int found = 0;
|
||||||
|
for(IColumnCallout callout : callouts) {
|
||||||
|
if (callout instanceof CalloutInfoWindow) {
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(found==1, CalloutInfoWindow.class.getName() + " not found for AD_InfoWindow.AD_Table_ID");
|
||||||
|
|
||||||
|
callouts = ColumnCalloutManager.findCallout("AD_InfoColumn", "AD_Element_ID");
|
||||||
|
assertNotNull(callouts, "Null column callouts for AD_InfoColumn.AD_Element_ID");
|
||||||
|
assertTrue(callouts.size() > 0, "Empty column callouts for AD_InfoColumn.AD_Element_ID");
|
||||||
|
found = 0;
|
||||||
|
for(IColumnCallout callout : callouts) {
|
||||||
|
if (callout instanceof CalloutInfoWindow) {
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(found==1, CalloutInfoWindow.class.getName() + " not found for AD_InfoColumn.AD_Element_ID");
|
||||||
|
|
||||||
|
callouts = ColumnCalloutManager.findCallout("AD_InfoColumn", "AD_Reference_ID");
|
||||||
|
assertNotNull(callouts, "Null column callouts for AD_InfoColumn.AD_Reference_ID");
|
||||||
|
assertTrue(callouts.size() > 0, "Empty column callouts for AD_InfoColumn.AD_Reference_ID");
|
||||||
|
found = 0;
|
||||||
|
for(IColumnCallout callout : callouts) {
|
||||||
|
if (callout instanceof CalloutInfoWindow) {
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(found==1, CalloutInfoWindow.class.getName() + " not found for AD_InfoColumn.AD_Reference_ID");
|
||||||
|
|
||||||
|
String calloutClass = "org.adempiere.base.callout.CostAdjustmentLineASI";
|
||||||
|
callouts = ColumnCalloutManager.findCallout(I_M_InventoryLine.Table_Name, I_M_InventoryLine.COLUMNNAME_M_AttributeSetInstance_ID);
|
||||||
|
assertNotNull(callouts, "Null column callouts for "+I_M_InventoryLine.Table_Name+"."+I_M_InventoryLine.COLUMNNAME_M_AttributeSetInstance_ID);
|
||||||
|
assertTrue(callouts.size() > 0, "Empty column callouts for "+I_M_InventoryLine.Table_Name+"."+I_M_InventoryLine.COLUMNNAME_M_AttributeSetInstance_ID);
|
||||||
|
found = 0;
|
||||||
|
for(IColumnCallout callout : callouts) {
|
||||||
|
if (callout.getClass().getName().equals(calloutClass)) {
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(found==1, calloutClass+" not found for "+I_M_InventoryLine.Table_Name+"."
|
||||||
|
+I_M_InventoryLine.COLUMNNAME_M_AttributeSetInstance_ID);
|
||||||
|
|
||||||
|
calloutClass = "org.adempiere.base.callout.CostAdjustmentLineProduct";
|
||||||
|
callouts = ColumnCalloutManager.findCallout(I_M_InventoryLine.Table_Name, I_M_InventoryLine.COLUMNNAME_M_Product_ID);
|
||||||
|
assertNotNull(callouts, "Null column callouts for "+I_M_InventoryLine.Table_Name+"."+I_M_InventoryLine.COLUMNNAME_M_Product_ID);
|
||||||
|
assertTrue(callouts.size() > 0, "Empty column callouts for "+I_M_InventoryLine.Table_Name+"."+I_M_InventoryLine.COLUMNNAME_M_Product_ID);
|
||||||
|
found = 0;
|
||||||
|
for(IColumnCallout callout : callouts) {
|
||||||
|
if (callout.getClass().getName().equals(calloutClass)) {
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(found==1, calloutClass+" not found for "+I_M_InventoryLine.Table_Name+"."
|
||||||
|
+I_M_InventoryLine.COLUMNNAME_M_Product_ID);
|
||||||
|
|
||||||
|
calloutClass = "org.adempiere.base.callout.CostAdjustmentLineProduct";
|
||||||
|
callouts = ColumnCalloutManager.findCallout(I_M_InventoryLine.Table_Name, I_M_InventoryLine.COLUMNNAME_M_AttributeSetInstance_ID);
|
||||||
|
assertNotNull(callouts, "Null column callouts for "+I_M_InventoryLine.Table_Name+"."+I_M_InventoryLine.COLUMNNAME_M_AttributeSetInstance_ID);
|
||||||
|
assertTrue(callouts.size() > 0, "Empty column callouts for "+I_M_InventoryLine.Table_Name+"."+I_M_InventoryLine.COLUMNNAME_M_AttributeSetInstance_ID);
|
||||||
|
found = 0;
|
||||||
|
for(IColumnCallout callout : callouts) {
|
||||||
|
if (callout.getClass().getName().equals(calloutClass)) {
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(found==0, calloutClass+" found for "+I_M_InventoryLine.Table_Name+"."
|
||||||
|
+I_M_InventoryLine.COLUMNNAME_M_AttributeSetInstance_ID);
|
||||||
|
|
||||||
|
calloutClass = "org.adempiere.model.CalloutBPartnerQuickEntry";
|
||||||
|
callouts = ColumnCalloutManager.findCallout(MBPartner.Table_Name, MBPartner.COLUMNNAME_Name);
|
||||||
|
assertNotNull(callouts, "Null column callouts for "+MBPartner.Table_Name+"."+MBPartner.COLUMNNAME_Name);
|
||||||
|
assertTrue(callouts.size() > 0, "Empty column callouts for "+MBPartner.Table_Name+"."+MBPartner.COLUMNNAME_Name);
|
||||||
|
found = 0;
|
||||||
|
for(IColumnCallout callout : callouts) {
|
||||||
|
if (callout.getClass().getName().equals(calloutClass)) {
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(found==1, calloutClass+" not found for "+MBPartner.Table_Name+"."
|
||||||
|
+MBPartner.COLUMNNAME_Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCoreCalloutMapping() {
|
||||||
|
Query query = new Query(Env.getCtx(), MColumn.Table_Name, "AD_Column.IsActive='Y' AND AD_Column.AD_Column_ID < 1000000 "
|
||||||
|
+ "AND AD_Table.IsActive='Y' AND AD_Table.AD_Table_ID < 1000000 "
|
||||||
|
+ "AND AD_Column.Callout IS NOT NULL ", getTrxName());
|
||||||
|
query.addJoinClause("JOIN AD_Table ON (AD_Column.AD_Table_ID=AD_Table.AD_Table_ID)");
|
||||||
|
query.addJoinClause("JOIN AD_Tab ON (AD_Table.AD_Table_ID=AD_Tab.AD_Table_ID AND AD_Tab.IsActive='Y' AND AD_Tab.AD_Tab_ID<1000000)");
|
||||||
|
query.addJoinClause("JOIN AD_Window ON (AD_Tab.AD_Window_ID=AD_Window.AD_Window_ID AND AD_Window.IsActive='Y' AND AD_Window.AD_Window_ID<1000000)");
|
||||||
|
query.addJoinClause("JOIN AD_Menu ON (AD_Window.AD_Window_ID=AD_Menu.AD_Window_ID AND AD_Menu.IsActive='Y' AND AD_Menu.AD_Menu_ID<1000000)");
|
||||||
|
List<MColumn> columns = query.list();
|
||||||
|
ClassLoader baseClassLoader = Adempiere.class.getClassLoader();
|
||||||
|
int calloutCount = 0;
|
||||||
|
for(MColumn column : columns) {
|
||||||
|
StringTokenizer st = new StringTokenizer(column.getCallout(), ";,", false);
|
||||||
|
while (st.hasMoreTokens()) {
|
||||||
|
String cmd = st.nextToken().trim();
|
||||||
|
|
||||||
|
if (cmd.toLowerCase().startsWith(MRule.SCRIPT_PREFIX))
|
||||||
|
continue;
|
||||||
|
int methodStart = cmd.lastIndexOf('.');
|
||||||
|
try {
|
||||||
|
if (methodStart != -1) // no class
|
||||||
|
{
|
||||||
|
String className = cmd.substring(0,methodStart);
|
||||||
|
String method = cmd.substring(methodStart+1);
|
||||||
|
Callout callout = Core.getCallout(className, method);
|
||||||
|
if (callout == null) {
|
||||||
|
//no match from factory, check java classpath
|
||||||
|
Class<?> cClass = baseClassLoader.loadClass(className);
|
||||||
|
callout = (Callout)cClass.getDeclaredConstructor().newInstance();
|
||||||
|
}
|
||||||
|
assertNotNull(callout, "Can't get callout "+cmd+" for "+column.getAD_Table()+" "+column);
|
||||||
|
calloutCount++;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
fail("Can't get callout "+cmd+" for "+column.getAD_Table()+" "+column, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(calloutCount > 0, "Zero callout loaded");
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,7 @@ import org.compiere.model.GridTab;
|
||||||
import org.compiere.model.MTest;
|
import org.compiere.model.MTest;
|
||||||
import org.idempiere.test.AbstractTestCase;
|
import org.idempiere.test.AbstractTestCase;
|
||||||
import org.idempiere.test.TestActivator;
|
import org.idempiere.test.TestActivator;
|
||||||
|
import org.idempiere.test.model.annotated.MyAnnotatedTestQtyCallout;
|
||||||
import org.junit.jupiter.api.Order;
|
import org.junit.jupiter.api.Order;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.TestMethodOrder;
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
|
@ -67,6 +68,11 @@ public class MappedColumnCalloutFactoryTest extends AbstractTestCase {
|
||||||
var list = Core.findCallout(MTest.Table_Name, MTest.COLUMNNAME_T_Amount);
|
var list = Core.findCallout(MTest.Table_Name, MTest.COLUMNNAME_T_Amount);
|
||||||
var optional = list.stream().filter(e -> e instanceof MyTestAmountCallout).findFirst();
|
var optional = list.stream().filter(e -> e instanceof MyTestAmountCallout).findFirst();
|
||||||
assertTrue(optional.isPresent(), "Can't find MyTestAmountCallout column callout for " + MTest.Table_Name + "." + MTest.COLUMNNAME_T_Amount);
|
assertTrue(optional.isPresent(), "Can't find MyTestAmountCallout column callout for " + MTest.Table_Name + "." + MTest.COLUMNNAME_T_Amount);
|
||||||
|
|
||||||
|
factory.scan(TestActivator.context, "org.idempiere.test.model.annotated");
|
||||||
|
list = Core.findCallout(MTest.Table_Name, MTest.COLUMNNAME_T_Qty);
|
||||||
|
optional = list.stream().filter(e -> e instanceof MyAnnotatedTestQtyCallout).findFirst();
|
||||||
|
assertTrue(optional.isPresent(), "Can't find MyAnnotatedTestQtyCallout column callout for " + MTest.Table_Name + "." + MTest.COLUMNNAME_T_Qty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* 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., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - hengsin *
|
||||||
|
**********************************************************************/
|
||||||
|
package org.idempiere.test.model.annotated;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.adempiere.base.IColumnCallout;
|
||||||
|
import org.adempiere.base.annotation.Callout;
|
||||||
|
import org.compiere.model.GridField;
|
||||||
|
import org.compiere.model.GridTab;
|
||||||
|
import org.compiere.model.MTest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Callout(tableName = MTest.Table_Name, columnName = MTest.COLUMNNAME_T_Qty)
|
||||||
|
public class MyAnnotatedTestQtyCallout implements IColumnCallout {
|
||||||
|
|
||||||
|
public MyAnnotatedTestQtyCallout() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String start(Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value, Object oldValue) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue