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: .
|
||||
Automatic-Module-Name: org.adempiere.base.callout
|
||||
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/,\
|
||||
OSGI-INF/costadjustmentcalloutfactory.xml,\
|
||||
OSGI-INF/,\
|
||||
.
|
||||
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 org.adempiere.base.IColumnCallout;
|
||||
import org.adempiere.base.annotation.Callout;
|
||||
import org.compiere.model.GridField;
|
||||
import org.compiere.model.GridTab;
|
||||
import org.compiere.model.MBPartner;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
@Callout(tableName = MBPartner.Table_Name, columnName = "*")
|
||||
public class CalloutBPartnerQuickEntry implements IColumnCallout {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?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">
|
||||
<implementation class="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">
|
||||
<service>
|
||||
<provide interface="org.adempiere.base.IColumnCalloutFactory"/>
|
||||
</service>
|
||||
<implementation class="org.adempiere.base.DefaultAnnotationBasedColumnCalloutFactory"/>
|
||||
</scr:component>
|
|
@ -64,36 +64,6 @@
|
|||
</run>
|
||||
</application>
|
||||
</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
|
||||
id="org.compiere.model.StandardTaxProvider"
|
||||
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 org.osgi.framework.BundleContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengsin
|
||||
|
@ -49,4 +51,10 @@ public interface IMappedColumnCalloutFactory {
|
|||
*/
|
||||
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;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
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 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
|
||||
|
@ -42,6 +55,8 @@ import org.osgi.service.component.annotations.Component;
|
|||
property = {"service.ranking:Integer=1"})
|
||||
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<>();
|
||||
|
||||
/**
|
||||
|
@ -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 org.adempiere.base.IColumnCallout;
|
||||
import org.adempiere.base.annotation.Callout;
|
||||
import org.compiere.model.AccessSqlParser;
|
||||
import org.compiere.model.AccessSqlParser.TableInfo;
|
||||
import org.compiere.model.GridField;
|
||||
|
@ -35,6 +36,8 @@ import org.compiere.util.Env;
|
|||
* @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 {
|
||||
|
||||
/**
|
||||
|
|
|
@ -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.idempiere.test.AbstractTestCase;
|
||||
import org.idempiere.test.TestActivator;
|
||||
import org.idempiere.test.model.annotated.MyAnnotatedTestQtyCallout;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
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 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);
|
||||
|
||||
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
|
||||
|
|
|
@ -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