IDEMPIERE-4675 Add model factory base class backed by Map and Lambda … (#555)
- added interface and default mapped model factory service - added unit test for default mapped model factory service
This commit is contained in:
parent
4009c9c8ca
commit
0f263f1c79
|
@ -25,6 +25,11 @@
|
||||||
<arguments>
|
<arguments>
|
||||||
</arguments>
|
</arguments>
|
||||||
</buildCommand>
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.ds.core.builder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
</buildSpec>
|
</buildSpec>
|
||||||
<natures>
|
<natures>
|
||||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
classpath=true
|
||||||
|
dsVersion=V1_3
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
enabled=true
|
||||||
|
generateBundleActivationPolicyLazy=true
|
||||||
|
path=OSGI-INF
|
||||||
|
validationErrorLevel=error
|
||||||
|
validationErrorLevel.missingImplicitUnbindMethod=error
|
|
@ -90,6 +90,7 @@ Import-Package: com.google.zxing,
|
||||||
org.osgi.framework,
|
org.osgi.framework,
|
||||||
org.osgi.service.cm;version="1.3.0",
|
org.osgi.service.cm;version="1.3.0",
|
||||||
org.osgi.service.component;version="1.1.0",
|
org.osgi.service.component;version="1.1.0",
|
||||||
|
org.osgi.service.component.annotations;version="1.3.0",
|
||||||
org.osgi.service.component.runtime;version="1.3.0",
|
org.osgi.service.component.runtime;version="1.3.0",
|
||||||
org.osgi.service.component.runtime.dto;version="1.3.0",
|
org.osgi.service.component.runtime.dto;version="1.3.0",
|
||||||
org.osgi.service.event;version="1.2.0",
|
org.osgi.service.event;version="1.2.0",
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="org.idempiere.model.MappedModelFactory">
|
||||||
|
<property name="service.ranking" type="Integer" value="1"/>
|
||||||
|
<service>
|
||||||
|
<provide interface="org.adempiere.base.IModelFactory"/>
|
||||||
|
<provide interface="org.idempiere.model.IMappedModelFactory"/>
|
||||||
|
</service>
|
||||||
|
<implementation class="org.idempiere.model.MappedModelFactory"/>
|
||||||
|
</scr:component>
|
|
@ -55,6 +55,7 @@ import org.idempiere.distributed.IMessageService;
|
||||||
import org.idempiere.fa.service.api.DepreciationFactoryLookupDTO;
|
import org.idempiere.fa.service.api.DepreciationFactoryLookupDTO;
|
||||||
import org.idempiere.fa.service.api.IDepreciationMethod;
|
import org.idempiere.fa.service.api.IDepreciationMethod;
|
||||||
import org.idempiere.fa.service.api.IDepreciationMethodFactory;
|
import org.idempiere.fa.service.api.IDepreciationMethodFactory;
|
||||||
|
import org.idempiere.model.IMappedModelFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a facade class for the Service Locator.
|
* This is a facade class for the Service Locator.
|
||||||
|
@ -923,5 +924,25 @@ public class Core {
|
||||||
}
|
}
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IServiceReferenceHolder<IMappedModelFactory> s_mappedModelFactoryReference = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return {@link IMappedModelFactory}
|
||||||
|
*/
|
||||||
|
public static IMappedModelFactory getMappedModelFactory(){
|
||||||
|
IMappedModelFactory modelFactoryService = null;
|
||||||
|
if (s_mappedModelFactoryReference != null) {
|
||||||
|
modelFactoryService = s_mappedModelFactoryReference.getService();
|
||||||
|
if (modelFactoryService != null)
|
||||||
|
return modelFactoryService;
|
||||||
|
}
|
||||||
|
IServiceReferenceHolder<IMappedModelFactory> serviceReference = Service.locator().locate(IMappedModelFactory.class).getServiceReference();
|
||||||
|
if (serviceReference != null) {
|
||||||
|
modelFactoryService = serviceReference.getService();
|
||||||
|
s_mappedModelFactoryReference = serviceReference;
|
||||||
|
}
|
||||||
|
return modelFactoryService;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* 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.model;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.compiere.model.PO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface IMappedModelFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add table name to class mapping
|
||||||
|
* @param tableName
|
||||||
|
* @param classSupplier
|
||||||
|
* @param recordIdFunction
|
||||||
|
* @param resultSetFunction
|
||||||
|
*/
|
||||||
|
void addMapping(String tableName, Supplier<Class<?>> classSupplier,
|
||||||
|
BiFunction<Integer, String, ? extends PO> recordIdFunction,
|
||||||
|
BiFunction<ResultSet, String, ? extends PO> resultSetFunction);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove table name to class mapping
|
||||||
|
* @param tableName
|
||||||
|
*/
|
||||||
|
void removeMapping(String tableName);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* 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.model;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.adempiere.base.IModelFactory;
|
||||||
|
import org.compiere.model.PO;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component(name = "org.idempiere.model.MappedModelFactory",
|
||||||
|
immediate = true,
|
||||||
|
service = {IModelFactory.class, IMappedModelFactory.class},
|
||||||
|
property = {"service.ranking:Integer=1"})
|
||||||
|
public class MappedModelFactory implements IModelFactory, IMappedModelFactory {
|
||||||
|
|
||||||
|
private final ConcurrentHashMap<String, Supplier<Class<?>>> classMap = new ConcurrentHashMap<>();
|
||||||
|
private final ConcurrentHashMap<String, BiFunction<Integer, String, ? extends PO>> recordIdMap = new ConcurrentHashMap<>();
|
||||||
|
private final ConcurrentHashMap<String, BiFunction<ResultSet, String, ? extends PO>> resultSetMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* default constructor
|
||||||
|
*/
|
||||||
|
public MappedModelFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getClass(String tableName) {
|
||||||
|
var supplier = classMap.get(tableName);
|
||||||
|
return supplier != null ? supplier.get() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PO getPO(String tableName, int Record_ID, String trxName) {
|
||||||
|
var function = recordIdMap.get(tableName);
|
||||||
|
return function != null ? function.apply(Record_ID, trxName) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PO getPO(String tableName, ResultSet rs, String trxName) {
|
||||||
|
var function = resultSetMap.get(tableName);
|
||||||
|
return function != null ? function.apply(rs, trxName) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addMapping(String tableName, Supplier<Class<?>> classSupplier, BiFunction<Integer, String, ? extends PO> recordIdFunction,
|
||||||
|
BiFunction<ResultSet, String, ? extends PO> resultSetFunction) {
|
||||||
|
classMap.put(tableName, classSupplier);
|
||||||
|
recordIdMap.put(tableName, recordIdFunction);
|
||||||
|
resultSetMap.put(tableName, resultSetFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeMapping(String tableName) {
|
||||||
|
classMap.remove(tableName);
|
||||||
|
recordIdMap.remove(tableName);
|
||||||
|
resultSetMap.remove(tableName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,126 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* 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.assertTrue;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.util.Dictionary;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.adempiere.base.Core;
|
||||||
|
import org.adempiere.base.IModelFactory;
|
||||||
|
import org.compiere.model.MTable;
|
||||||
|
import org.compiere.model.PO;
|
||||||
|
import org.compiere.model.X_Test;
|
||||||
|
import org.compiere.util.CacheMgt;
|
||||||
|
import org.compiere.util.Env;
|
||||||
|
import org.idempiere.model.IMappedModelFactory;
|
||||||
|
import org.idempiere.model.MappedModelFactory;
|
||||||
|
import org.idempiere.test.AbstractTestCase;
|
||||||
|
import org.idempiere.test.TestActivator;
|
||||||
|
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
|
||||||
|
import org.junit.jupiter.api.Order;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.TestMethodOrder;
|
||||||
|
import org.osgi.framework.BundleContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@TestMethodOrder(OrderAnnotation.class)
|
||||||
|
public class MappedModelFactoryTest extends AbstractTestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public MappedModelFactoryTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(1)
|
||||||
|
public void testDefaultMappedModelFactory() {
|
||||||
|
IMappedModelFactory mappedFactory = Core.getMappedModelFactory();
|
||||||
|
mappedFactory.addMapping(MyTest.Table_Name, () -> MyTest.class, (id, trxName) -> new MyTest(Env.getCtx(), id, trxName),
|
||||||
|
(rs, trxName) -> new MyTest(Env.getCtx(), rs, trxName));
|
||||||
|
PO po = MTable.get(MyTest.Table_ID).getPO(0, getTrxName());
|
||||||
|
assertTrue(po instanceof MyTest, "PO not instanceof MyTest. PO.className="+po.getClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(2)
|
||||||
|
public void testCustomMappedModelFactory() {
|
||||||
|
BundleContext bc = TestActivator.context;
|
||||||
|
Dictionary<String, Object> properties = new Hashtable<String, Object>();
|
||||||
|
properties.put("service.ranking", Integer.valueOf(2));
|
||||||
|
bc.registerService(IModelFactory.class, new MyFactory(), properties);
|
||||||
|
CacheMgt.get().reset();
|
||||||
|
PO po = MTable.get(MyTest2.Table_ID).getPO(0, getTrxName());
|
||||||
|
assertTrue(po instanceof MyTest2, "PO not instanceof MyTest2. PO.className="+po.getClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static class MyFactory extends MappedModelFactory {
|
||||||
|
|
||||||
|
public MyFactory() {
|
||||||
|
addMapping(MyTest2.Table_Name, () -> MyTest2.class, (id, trxName) -> new MyTest2(Env.getCtx(), id, trxName),
|
||||||
|
(rs, trxName) -> new MyTest2(Env.getCtx(), rs, trxName));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static class MyTest extends X_Test {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 2010413233032792416L;
|
||||||
|
|
||||||
|
public MyTest(Properties ctx, int Test_ID, String trxName) {
|
||||||
|
super(ctx, Test_ID, trxName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyTest(Properties ctx, ResultSet rs, String trxName) {
|
||||||
|
super(ctx, rs, trxName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static class MyTest2 extends X_Test {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 2010413233032792416L;
|
||||||
|
|
||||||
|
public MyTest2(Properties ctx, int Test_ID, String trxName) {
|
||||||
|
super(ctx, Test_ID, trxName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyTest2(Properties ctx, ResultSet rs, String trxName) {
|
||||||
|
super(ctx, rs, trxName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue