From a02e1469a14dce65bbdbae4068d1aadf62c70506 Mon Sep 17 00:00:00 2001 From: homedirectory Date: Thu, 25 Apr 2024 14:57:50 +0300 Subject: [PATCH 01/25] #2244 Remove deprecated DB-driven test support --- .../test/IDbDrivenTestCaseConfiguration.java | 24 -- ...TaxSensitiveMoneyDbOperationsTestCase.java | 4 +- .../platform/test/DbDrivenTestCase.java | 212 ------------------ ...PlatformDbDrivenTestCaseConfiguration.java | 192 ---------------- ...formDomainDrivenTestCaseConfiguration.java | 3 - .../src/test/resources/test.properties | 6 - .../web/test/server/DataPopulationConfig.java | 3 - .../test/IWebDrivenTestCaseConfiguration.java | 25 --- .../platform/web/test/WebBasedTestCase.java | 71 +----- ...tformWebDbDrivenTestCaseConfiguration.java | 143 ------------ ...latformWebDrivenTestCaseConfiguration.java | 49 ---- .../WebResourceGuardTestCase.java | 5 +- .../src/test/resources/test.properties | 3 +- 13 files changed, 7 insertions(+), 733 deletions(-) delete mode 100644 platform-dao/src/main/java/ua/com/fielden/platform/test/IDbDrivenTestCaseConfiguration.java delete mode 100644 platform-dao/src/test/java/ua/com/fielden/platform/test/DbDrivenTestCase.java delete mode 100644 platform-dao/src/test/java/ua/com/fielden/platform/test/PlatformDbDrivenTestCaseConfiguration.java delete mode 100644 platform-dao/src/test/resources/test.properties delete mode 100644 platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/IWebDrivenTestCaseConfiguration.java delete mode 100644 platform-web-resources/src/test/java/ua/com/fielden/web/PlatformWebDbDrivenTestCaseConfiguration.java delete mode 100644 platform-web-resources/src/test/java/ua/com/fielden/web/PlatformWebDrivenTestCaseConfiguration.java diff --git a/platform-dao/src/main/java/ua/com/fielden/platform/test/IDbDrivenTestCaseConfiguration.java b/platform-dao/src/main/java/ua/com/fielden/platform/test/IDbDrivenTestCaseConfiguration.java deleted file mode 100644 index e61d2115ff..0000000000 --- a/platform-dao/src/main/java/ua/com/fielden/platform/test/IDbDrivenTestCaseConfiguration.java +++ /dev/null @@ -1,24 +0,0 @@ -package ua.com.fielden.platform.test; - -import java.util.List; - -import com.google.inject.Injector; - -import ua.com.fielden.platform.entity.factory.EntityFactory; -import ua.com.fielden.platform.persistence.HibernateUtil; - -/** - * Contract for configuration used by db driven test cases such as {@link DbDrivenTestCase}. - * - * @author TG Team - * - */ -public interface IDbDrivenTestCaseConfiguration { - EntityFactory getEntityFactory(); - - Injector getInjector(); - - HibernateUtil getHibernateUtil(); - - List getDdl(); -} \ No newline at end of file diff --git a/platform-dao/src/test/java/ua/com/fielden/platform/persistence/types/TaxSensitiveMoneyDbOperationsTestCase.java b/platform-dao/src/test/java/ua/com/fielden/platform/persistence/types/TaxSensitiveMoneyDbOperationsTestCase.java index 72b46fb876..5b29b4f015 100644 --- a/platform-dao/src/test/java/ua/com/fielden/platform/persistence/types/TaxSensitiveMoneyDbOperationsTestCase.java +++ b/platform-dao/src/test/java/ua/com/fielden/platform/persistence/types/TaxSensitiveMoneyDbOperationsTestCase.java @@ -12,8 +12,6 @@ import ua.com.fielden.platform.dao.IEntityDao; import ua.com.fielden.platform.entity.factory.ICompanionObjectFinder; -import ua.com.fielden.platform.sample.domain.TgWorkOrder; -import ua.com.fielden.platform.test.DbDrivenTestCase; import ua.com.fielden.platform.test_config.AbstractDaoTestCase; import ua.com.fielden.platform.types.Money; @@ -90,4 +88,4 @@ protected void populateDomain() { save(new_(EntityWithTaxMoney.class, "aname1").setMoney(new Money(new BigDecimal("100.00"), new BigDecimal("9.09"), Currency.getInstance("AUD")))); } -} \ No newline at end of file +} diff --git a/platform-dao/src/test/java/ua/com/fielden/platform/test/DbDrivenTestCase.java b/platform-dao/src/test/java/ua/com/fielden/platform/test/DbDrivenTestCase.java deleted file mode 100644 index 943b2d2cf9..0000000000 --- a/platform-dao/src/test/java/ua/com/fielden/platform/test/DbDrivenTestCase.java +++ /dev/null @@ -1,212 +0,0 @@ -package ua.com.fielden.platform.test; - -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.lang.reflect.Method; -import java.sql.Connection; -import java.sql.Statement; -import java.util.List; -import java.util.Properties; - -import org.apache.commons.lang3.StringUtils; -import org.dbunit.database.DatabaseConnection; -import org.dbunit.database.IDatabaseConnection; -import org.dbunit.dataset.CompositeDataSet; -import org.dbunit.dataset.IDataSet; -import org.dbunit.dataset.xml.FlatDtdDataSet; -import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; -import org.dbunit.operation.DatabaseOperation; -import org.hibernate.Session; -import org.hibernate.Transaction; - -import com.google.inject.Injector; - -import junit.framework.TestCase; -import static ua.com.fielden.platform.eql.dbschema.HibernateMappingsGenerator.ID_SEQUENCE_NAME; -import ua.com.fielden.platform.entity.factory.EntityFactory; -import ua.com.fielden.platform.error.Result; -import ua.com.fielden.platform.persistence.HibernateUtil; -import ua.com.fielden.platform.types.either.Either; -import ua.com.fielden.platform.types.try_wrapper.TryWrapper; - -/** - * This is base class for any db driven test case. It takes care about Hibernate configuration, session and transaction management as well as test db creation and data population. - * - * The details of Hibernate session creation, injector etc. are provided by a custom implementation of {@link IDbDrivenTestCaseConfiguration}, which is read from - * src/test/resources/test.properties. - * - * Please note that there can only be one base class for db driven test case per module (e.g. rma-dao, workorder-dao). - * - * @author 01es - * - */ -public abstract class DbDrivenTestCase extends TestCase { - - private enum DataSetReason { - INSERT, UPDATE; - } - - public static final IDbDrivenTestCaseConfiguration config = createConfig(); - private static String dbDdlFile; - private static String dbDtdFile; - - @SuppressWarnings("unchecked") - private static IDbDrivenTestCaseConfiguration createConfig() { - try { - final Properties testProps = new Properties(); - final FileInputStream in = new FileInputStream("src/test/resources/test.properties"); - testProps.load(in); - in.close(); - - dbDtdFile = StringUtils.isEmpty(testProps.getProperty("db-dtd-file")) ? "src/test/resources/data-files/db.dtd" : testProps.getProperty("db-dtd-file"); - dbDdlFile = StringUtils.isEmpty(testProps.getProperty("db-ddl-file")) ? "src/test/resources/db/testdb.ddl" : testProps.getProperty("db-ddl-file"); - - final String configClassName = testProps.getProperty("config"); - final Class type = (Class) Class.forName(configClassName); - return type.newInstance(); - } catch (final Exception e) { - throw new RuntimeException(e); - } - } - - public static final EntityFactory entityFactory = config.getEntityFactory(); - public static final Injector injector = config.getInjector(); - public static final HibernateUtil hibernateUtil = config.getHibernateUtil(); - - private Transaction transactionForTests; - - static { - // recreating db schema - final Session session = hibernateUtil.getSessionFactory().getCurrentSession(); - final Transaction tr = hibernateUtil.getSessionFactory().getCurrentSession().beginTransaction(); - final IDatabaseConnection connection = getConnection(session).orElseThrow(Result::asRuntime); - try (final Statement dropObjects = connection.getConnection().createStatement(); - final Statement createIdSequence = connection.getConnection().createStatement();) { - - dropObjects.execute("DROP ALL OBJECTS"); - createIdSequence.execute(String.format("CREATE SEQUENCE %s START WITH 10000 INCREMENT BY 1 MINVALUE 1 CACHE 3;", ID_SEQUENCE_NAME)); - - final List ddls = config.getDdl(); - if (ddls == null || ddls.isEmpty()) { - connection.getConnection().createStatement().execute("RUNSCRIPT FROM '" + dbDdlFile + "'"); - } else { - try { - for (final String sql : ddls) { - try { - session.createSQLQuery(sql).executeUpdate(); - } catch (final Exception e) { - e.printStackTrace(); - } - } - } catch (final Exception ex) { - tr.rollback(); - throw new IllegalStateException("Error upon DDL execution: " + ex); - } - } - // The following line of code ensures that database DTD is generated dynamically using the latest schema modifications - FlatDtdDataSet.write(connection.createDataSet(), new FileOutputStream(dbDtdFile)); - - tr.commit(); - } catch (final Exception e) { - System.err.println("Db initialisation failed: " + e.getMessage()); - tr.rollback(); - } - } - - /** - * This method should be implemented in descendants in order to provide list of paths to datasets, which are to be used with the given test case (via invoking method - * getDataSet()). The provided in files data is inserted into the database. - * - * @return - */ - protected abstract String[] getDataSetPathsForInsert(); - - /** - * Similar to {link #getDataSetPathsForInsert()}, but used to updating existing data. This is useful when an inserted as part of the data from getDataSetPathsForInsert record - * needs to be updated with a reference to a record that was inserted later also as part of the initial data setup. For example, vehicle may need to have a replacedBy property - * populated. At the insertion time this is not possible because the relevant replacement vehicle does not yet exist, which leads to referential integrity vilation. - *

- * By default an empty array of paths if returned. - * - * @return - */ - protected String[] getDataSetPathsForUpdate() { - return new String[] {}; - } - - protected static Either getConnection(final Session session) { - return TryWrapper.Try(() -> { - final Method getConnection = session.getClass().getDeclaredMethod("connection"); - return new DatabaseConnection((Connection) getConnection.invoke(session)); - }); - } - - /** - * This methods relies on the implementation of the method getDataSetPaths(). It also assumed that names of the flat dataset files should end with .flat.xml in order to be - * parsed correctly. Non flat dataset files are expected to conform to dataset.dtd. - * - * @return - * @throws java.lang.Exception - */ - protected IDataSet getDataSet(final DataSetReason reason) throws Exception { - IDataSet compositeDataSet = null; - final String[] dsPaths = reason == DataSetReason.INSERT ? getDataSetPathsForInsert() : getDataSetPathsForUpdate(); - if (dsPaths != null && dsPaths.length > 0) { - compositeDataSet = new CompositeDataSet(new FlatXmlDataSetBuilder().build(new FileInputStream(dsPaths[0]))); - } else if (reason == DataSetReason.INSERT) { - final String errorMessage = "Data for test case " + this.getClass().getName() - + " has not been provided. Pls override method getDataSetPaths in order to provide the list of paths to required datasets."; - throw new RuntimeException(errorMessage); - } - for (int index = 1; index < dsPaths.length; index++) { - compositeDataSet = new CompositeDataSet(compositeDataSet, new FlatXmlDataSetBuilder().build(new FileInputStream(dsPaths[index]))); - } - - return compositeDataSet; - } - - @Override - public void setUp() throws Exception { - super.setUp(); - final Session session = hibernateUtil.getSessionFactory().getCurrentSession(); - final Transaction localTransaction = hibernateUtil.getSessionFactory().getCurrentSession().beginTransaction(); - final IDatabaseConnection connection = getConnection(session).orElseThrow(Result::asRuntime); - try { - DatabaseOperation.CLEAN_INSERT.execute(connection, getDataSet(DataSetReason.INSERT)); - final IDataSet updateDataSet = getDataSet(DataSetReason.UPDATE); - if (updateDataSet != null) { - DatabaseOperation.UPDATE.execute(connection, updateDataSet); - } - } finally { - localTransaction.commit(); - } - // each test case to be executed in a separate transaction - final Session session1 = hibernateUtil.getSessionFactory().getCurrentSession(); - transactionForTests = session1.beginTransaction(); - } - - @Override - public void tearDown() throws Exception { - /* - * commit all changes performed within tests some test cases may require a manual transaction control; thus, the current transaction could be inactive at the tearDown stage - * -- hence the try/catch - */ - try { - transactionForTests.commit(); - } catch (final RuntimeException e) { - } - // delete all data from the test db - final Session session = hibernateUtil.getSessionFactory().getCurrentSession(); - final Transaction localTransaction = hibernateUtil.getSessionFactory().getCurrentSession().beginTransaction(); - final IDatabaseConnection connection = getConnection(session).orElseThrow(Result::asRuntime); - DatabaseOperation.DELETE_ALL.execute(connection, getDataSet(DataSetReason.INSERT)); - final IDataSet updateDataSet = getDataSet(DataSetReason.UPDATE); - if (updateDataSet != null) { - DatabaseOperation.DELETE_ALL.execute(connection, getDataSet(DataSetReason.UPDATE)); - } - - localTransaction.commit(); - hibernateUtil.getSessionFactory().getCurrentSession().close(); - super.tearDown(); - } -} \ No newline at end of file diff --git a/platform-dao/src/test/java/ua/com/fielden/platform/test/PlatformDbDrivenTestCaseConfiguration.java b/platform-dao/src/test/java/ua/com/fielden/platform/test/PlatformDbDrivenTestCaseConfiguration.java deleted file mode 100644 index 6b5406628a..0000000000 --- a/platform-dao/src/test/java/ua/com/fielden/platform/test/PlatformDbDrivenTestCaseConfiguration.java +++ /dev/null @@ -1,192 +0,0 @@ -package ua.com.fielden.platform.test; - -import static java.lang.String.format; - -import java.io.ByteArrayInputStream; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.sql.DriverManager; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import org.apache.commons.lang3.StringUtils; -import org.hibernate.HibernateException; -import org.hibernate.MappingException; -import org.hibernate.cfg.Configuration; -import org.hibernate.type.YesNoType; - -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.google.inject.Provider; - -import ua.com.fielden.platform.domain.PlatformDomainTypes; -import ua.com.fielden.platform.entity.AbstractEntity; -import ua.com.fielden.platform.entity.factory.EntityFactory; -import ua.com.fielden.platform.entity.meta.PropertyDescriptor; -import ua.com.fielden.platform.entity.query.DbVersion; -import ua.com.fielden.platform.entity.query.IdOnlyProxiedEntityTypeCache; -import ua.com.fielden.platform.entity.query.metadata.DomainMetadata; -import ua.com.fielden.platform.eql.dbschema.HibernateMappingsGenerator; -import ua.com.fielden.platform.ioc.ApplicationInjectorFactory; -import ua.com.fielden.platform.ioc.HibernateUserTypesModule; -import ua.com.fielden.platform.ioc.NewUserNotifierMockBindingModule; -import ua.com.fielden.platform.migration.LegacyConnectionModule; -import ua.com.fielden.platform.persistence.HibernateUtil; -import ua.com.fielden.platform.persistence.ProxyInterceptor; -import ua.com.fielden.platform.persistence.composite.EntityWithDynamicCompositeKey; -import ua.com.fielden.platform.persistence.types.DateTimeType; -import ua.com.fielden.platform.persistence.types.EntityWithExTaxAndTaxMoney; -import ua.com.fielden.platform.persistence.types.EntityWithMoney; -import ua.com.fielden.platform.persistence.types.EntityWithSimpleMoney; -import ua.com.fielden.platform.persistence.types.EntityWithSimpleTaxMoney; -import ua.com.fielden.platform.persistence.types.EntityWithTaxMoney; -import ua.com.fielden.platform.persistence.types.PropertyDescriptorType; -import ua.com.fielden.platform.persistence.types.SimpleMoneyType; -import ua.com.fielden.platform.sample.domain.TgFuelType; -import ua.com.fielden.platform.sample.domain.TgFuelUsage; -import ua.com.fielden.platform.sample.domain.TgOrgUnit1; -import ua.com.fielden.platform.sample.domain.TgOrgUnit2; -import ua.com.fielden.platform.sample.domain.TgOrgUnit3; -import ua.com.fielden.platform.sample.domain.TgOrgUnit4; -import ua.com.fielden.platform.sample.domain.TgOrgUnit5; -import ua.com.fielden.platform.sample.domain.TgTimesheet; -import ua.com.fielden.platform.sample.domain.TgVehicle; -import ua.com.fielden.platform.sample.domain.TgVehicleMake; -import ua.com.fielden.platform.sample.domain.TgVehicleModel; -import ua.com.fielden.platform.sample.domain.TgWorkOrder; -import ua.com.fielden.platform.test.entities.ComplexKeyEntity; -import ua.com.fielden.platform.test.entities.CompositeEntity; -import ua.com.fielden.platform.test.entities.CompositeEntityKey; -import ua.com.fielden.platform.test.ioc.DaoTestHibernateModule; -import ua.com.fielden.platform.types.Money; - -/** - * Provides platform specific implementation of {@link IDbDrivenTestCaseConfiguration}, which is mainly related to the use of {@link DaoTestHibernateModule}. - * - * @author TG Team - * - * @deprecated Use {@link PlatformDomainDrivenTestCaseConfiguration} instead. - * - */ -@Deprecated -public class PlatformDbDrivenTestCaseConfiguration implements IDbDrivenTestCaseConfiguration { - protected final EntityFactory entityFactory; - protected final Injector injector; - protected final HibernateUtil hibernateUtil; - - private final DaoTestHibernateModule hibernateModule; - - public static final List>> testDomain = new ArrayList>>(); - - public static final Map hibTypeDefaults = new HashMap(); - - static { - hibTypeDefaults.put(boolean.class, YesNoType.class); - hibTypeDefaults.put(Boolean.class, YesNoType.class); - hibTypeDefaults.put(Date.class, DateTimeType.class); - hibTypeDefaults.put(Money.class, SimpleMoneyType.class); - hibTypeDefaults.put(PropertyDescriptor.class, PropertyDescriptorType.class); - testDomain.addAll(PlatformDomainTypes.types); - testDomain.add(CompositeEntity.class); - testDomain.add(CompositeEntityKey.class); - testDomain.add(ComplexKeyEntity.class); - testDomain.add(EntityWithMoney.class); - testDomain.add(EntityWithTaxMoney.class); - testDomain.add(EntityWithExTaxAndTaxMoney.class); - testDomain.add(EntityWithSimpleTaxMoney.class); - testDomain.add(EntityWithSimpleMoney.class); - testDomain.add(EntityWithDynamicCompositeKey.class); - testDomain.add(TgTimesheet.class); - testDomain.add(TgVehicleMake.class); - testDomain.add(TgVehicleModel.class); - testDomain.add(TgVehicle.class); - testDomain.add(TgFuelUsage.class); - testDomain.add(TgFuelType.class); - testDomain.add(TgOrgUnit1.class); - testDomain.add(TgOrgUnit2.class); - testDomain.add(TgOrgUnit3.class); - testDomain.add(TgOrgUnit4.class); - testDomain.add(TgOrgUnit5.class); - testDomain.add(TgWorkOrder.class); - } - - /** - * Required for dynamic instantiation by {@link DbDrivenTestCase} - */ - public PlatformDbDrivenTestCaseConfiguration() { - // instantiate all the factories and Hibernate utility - - final ProxyInterceptor interceptor = new ProxyInterceptor(); - try { - final DomainMetadata domainMetadata = new DomainMetadata(hibTypeDefaults, Guice.createInjector(new HibernateUserTypesModule()), testDomain, DbVersion.H2); - final IdOnlyProxiedEntityTypeCache idOnlyProxiedEntityTypeCache = new IdOnlyProxiedEntityTypeCache(domainMetadata.eqlDomainMetadata); - final Configuration cfg = new Configuration(); - - try { - cfg.addInputStream(new ByteArrayInputStream(HibernateMappingsGenerator.generateMappings(domainMetadata.eqlDomainMetadata).getBytes("UTF8"))); - } catch (final MappingException | UnsupportedEncodingException e) { - throw new HibernateException("Could not add mappings.", e); - } - - // this is the old and now deprecated configuration than requires for some properties to be overridden - cfg.configure(new URL("file:src/test/resources/hibernate4test.cfg.xml")); - // let's override the database name if supplied to support forked execution of old test cases - final String databaseUri = System.getProperty("legacyTests.databaseUri"); - if (!StringUtils.isEmpty(databaseUri)) { - final Properties dbProps = new Properties(); - dbProps.setProperty("hibernate.connection.url", format("jdbc:h2:%s;INIT=SET REFERENTIAL_INTEGRITY FALSE", databaseUri)); - cfg.addProperties(dbProps); - } - - hibernateUtil = new HibernateUtil(interceptor, cfg); - hibernateModule = new DaoTestHibernateModule(hibernateUtil.getSessionFactory(), domainMetadata, idOnlyProxiedEntityTypeCache); - injector = new ApplicationInjectorFactory().add(hibernateModule).add(new NewUserNotifierMockBindingModule()).add(new LegacyConnectionModule(new Provider() { - @Override - public Object get() { - try { - final String connectionUrl = "jdbc:h2:mem:db;DB_CLOSE_DELAY=-1"; - Class.forName("org.h2.Driver"); - return DriverManager.getConnection(connectionUrl, "sa", ""); - } catch (final Exception e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - })).getInjector(); - entityFactory = injector.getInstance(EntityFactory.class); - interceptor.setFactory(entityFactory); - - // bind domain specific validation classes - // hibernateModule.getDomainValidationConfig().setValidator(Advice.class, "road", new AdviceRoadValidator()).setValidator(Advice.class, "carrier", injector.getInstance(AdviceCarrierValidator.class)).setValidator(AdvicePosition.class, "rotable", new AdvicePositionRotableValidator()); - // bind domain specific meta property configuration classes - // hibernateModule.getDomainMetaPropertyConfig().setDefiner(Advice.class, "dispatchedToWorkshop", new AdviceDispatchedToWorkshopMetaDefiner()).setDefiner(Advice.class, "road", new AdviceRoadMetaDefiner()); - } catch (final Exception e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - - @Override - public EntityFactory getEntityFactory() { - return entityFactory; - } - - @Override - public HibernateUtil getHibernateUtil() { - return hibernateUtil; - } - - @Override - public Injector getInjector() { - return injector; - } - - @Override - public List getDdl() { - return null; - } -} \ No newline at end of file diff --git a/platform-dao/src/test/java/ua/com/fielden/platform/test/PlatformDomainDrivenTestCaseConfiguration.java b/platform-dao/src/test/java/ua/com/fielden/platform/test/PlatformDomainDrivenTestCaseConfiguration.java index 30004e99a5..4b1209d8ce 100644 --- a/platform-dao/src/test/java/ua/com/fielden/platform/test/PlatformDomainDrivenTestCaseConfiguration.java +++ b/platform-dao/src/test/java/ua/com/fielden/platform/test/PlatformDomainDrivenTestCaseConfiguration.java @@ -24,9 +24,6 @@ public final class PlatformDomainDrivenTestCaseConfiguration implements IDomainD private final Injector injector; private final PlatformTestServerModule hibernateModule; - /** - * Required for dynamic instantiation by {@link DbDrivenTestCase} - */ public PlatformDomainDrivenTestCaseConfiguration(final Properties hbc) { // instantiate all the factories and Hibernate utility try { diff --git a/platform-dao/src/test/resources/test.properties b/platform-dao/src/test/resources/test.properties deleted file mode 100644 index 2779054998..0000000000 --- a/platform-dao/src/test/resources/test.properties +++ /dev/null @@ -1,6 +0,0 @@ -## Class implementing ua.com.fielden.platform.test.IDbDrivenTestCaseConfiguration -config = ua.com.fielden.platform.test.PlatformDbDrivenTestCaseConfiguration -## a file name including a full path that contain DDL for test database generation -db-ddl-file = src/test/resources/db/testdb.ddl -## a file name including a full path that should contain DTD for test database -db-dtd-file = src/test/resources/data-files/db.dtd \ No newline at end of file diff --git a/platform-web-resources/src/main/java/ua/com/fielden/platform/web/test/server/DataPopulationConfig.java b/platform-web-resources/src/main/java/ua/com/fielden/platform/web/test/server/DataPopulationConfig.java index 08fc5bcb00..542cfc47f1 100644 --- a/platform-web-resources/src/main/java/ua/com/fielden/platform/web/test/server/DataPopulationConfig.java +++ b/platform-web-resources/src/main/java/ua/com/fielden/platform/web/test/server/DataPopulationConfig.java @@ -26,9 +26,6 @@ public final class DataPopulationConfig implements IDomainDrivenTestCaseConfigur private final Injector injector; private final TgTestApplicationServerModule module; - /** - * Default constructor is required for dynamic instantiation by {@code DbDrivenTestCase}. - */ public DataPopulationConfig(final Properties props) { // instantiate all the factories and Hibernate utility try { diff --git a/platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/IWebDrivenTestCaseConfiguration.java b/platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/IWebDrivenTestCaseConfiguration.java deleted file mode 100644 index 461632ee16..0000000000 --- a/platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/IWebDrivenTestCaseConfiguration.java +++ /dev/null @@ -1,25 +0,0 @@ -package ua.com.fielden.platform.web.test; - -import com.google.inject.Injector; - -import ua.com.fielden.platform.entity.factory.EntityFactory; -import ua.com.fielden.platform.test.IDbDrivenTestCaseConfiguration; -import ua.com.fielden.platform.web.resources.RestServerUtil; - -/** - * Contract for configuration used by web driven test cases, which are derived from {@link WebBasedTestCase}. - * - * @author TG Team - * - */ -public interface IWebDrivenTestCaseConfiguration { - final static int PORT = 9042; - - EntityFactory entityFactory(); - - Injector injector(); - - RestServerUtil restServerUtil(); - - void setDbDrivenTestConfiguration(IDbDrivenTestCaseConfiguration config); -} diff --git a/platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/WebBasedTestCase.java b/platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/WebBasedTestCase.java index 9b04b0f2ac..21b286c406 100644 --- a/platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/WebBasedTestCase.java +++ b/platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/WebBasedTestCase.java @@ -1,17 +1,10 @@ package ua.com.fielden.platform.web.test; -import java.io.FileInputStream; -import java.util.Properties; - -import org.junit.After; -import org.junit.Before; import org.restlet.Application; import org.restlet.Component; import org.restlet.Restlet; import org.restlet.data.Protocol; -import ua.com.fielden.platform.test.DbDrivenTestCase; - /** * This is a base class for web-driven testing of resources and RAOs. It is responsible for auto-configuration of a web-server listening on port 9000. *

@@ -38,10 +31,11 @@ * @author TG Team * */ -public abstract class WebBasedTestCase extends Application { +public abstract class WebBasedTestCase { protected static final Component component = new Component(); + public static final int PORT = 9042; static { - component.getServers().add(Protocol.HTTP, IWebDrivenTestCaseConfiguration.PORT); + component.getServers().add(Protocol.HTTP, PORT); try { component.start(); } catch (final Exception e) { @@ -78,64 +72,5 @@ public static void detachWebApplication(final Restlet restlet) { System.exit(100); } } - protected DbDrivenTestCase dbDrivenTestCase = new DbDrivenTestCase() { - @Override - protected String[] getDataSetPathsForInsert() { - return WebBasedTestCase.this.getDataSetPaths(); - } - }; - - protected final IWebDrivenTestCaseConfiguration config = createConfig(); - - private static IWebDrivenTestCaseConfiguration createConfig() { - try { - final Properties testProps = new Properties(); - final FileInputStream in = new FileInputStream("src/test/resources/test.properties"); - testProps.load(in); - in.close(); - final String configClassName = testProps.getProperty("web-config"); - final Class type = (Class) Class.forName(configClassName); - final IWebDrivenTestCaseConfiguration webConf = type.newInstance(); - webConf.setDbDrivenTestConfiguration(DbDrivenTestCase.config); - return webConf; - } catch (final Exception e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - @Before - public void setUp() { - try { - attachWebApplication("/v1", this); // needed for application versioned resources - attachWebApplication("/system", this); // needed for application unversioned resources such as authentication resource - if (getDataSetPaths() != null && getDataSetPaths().length > 0) { - dbDrivenTestCase.setUp(); - } - } catch (final Exception e) { - e.printStackTrace(); - System.exit(100); - } - } - - @After - public void tearDown() { - try { - detachWebApplication(this); - if (getDataSetPaths() != null && getDataSetPaths().length > 0) { - dbDrivenTestCase.tearDown(); - } - } catch (final Exception e) { - e.printStackTrace(); - System.exit(100); - } - } - - /** - * This method should be implemented in descendants in order to provide list of paths to datasets, which are to be used with the given test case (via invoking method - * getDataSet()). - * - * @return - */ - protected abstract String[] getDataSetPaths(); } diff --git a/platform-web-resources/src/test/java/ua/com/fielden/web/PlatformWebDbDrivenTestCaseConfiguration.java b/platform-web-resources/src/test/java/ua/com/fielden/web/PlatformWebDbDrivenTestCaseConfiguration.java deleted file mode 100644 index d1e1b21945..0000000000 --- a/platform-web-resources/src/test/java/ua/com/fielden/web/PlatformWebDbDrivenTestCaseConfiguration.java +++ /dev/null @@ -1,143 +0,0 @@ -package ua.com.fielden.web; - -import java.io.ByteArrayInputStream; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.hibernate.HibernateException; -import org.hibernate.MappingException; -import org.hibernate.cfg.Configuration; - -import com.google.inject.Guice; -import com.google.inject.Injector; - -import ua.com.fielden.platform.attachment.Attachment; -import ua.com.fielden.platform.entity.AbstractEntity; -import ua.com.fielden.platform.entity.factory.EntityFactory; -import ua.com.fielden.platform.entity.functional.master.AcknowledgeWarnings; -import ua.com.fielden.platform.entity.functional.master.PropertyWarning; -import ua.com.fielden.platform.entity.query.DbVersion; -import ua.com.fielden.platform.entity.query.IdOnlyProxiedEntityTypeCache; -import ua.com.fielden.platform.entity.query.metadata.DomainMetadata; -import ua.com.fielden.platform.eql.dbschema.HibernateMappingsGenerator; -import ua.com.fielden.platform.ioc.ApplicationInjectorFactory; -import ua.com.fielden.platform.ioc.HibernateUserTypesModule; -import ua.com.fielden.platform.persistence.HibernateUtil; -import ua.com.fielden.platform.persistence.ProxyInterceptor; -import ua.com.fielden.platform.persistence.types.DateTimeType; -import ua.com.fielden.platform.persistence.types.MoneyUserType; -import ua.com.fielden.platform.security.SecurityRoleAssociationBatchAction; -import ua.com.fielden.platform.security.UserAndRoleAssociationBatchAction; -import ua.com.fielden.platform.security.user.SecurityRoleAssociation; -import ua.com.fielden.platform.security.user.SecurityTokenInfo; -import ua.com.fielden.platform.security.user.User; -import ua.com.fielden.platform.security.user.UserAndRoleAssociation; -import ua.com.fielden.platform.security.user.UserRole; -import ua.com.fielden.platform.security.user.UserRoleTokensUpdater; -import ua.com.fielden.platform.security.user.UserRolesUpdater; -import ua.com.fielden.platform.security.user.UserSecret; -import ua.com.fielden.platform.serialisation.api.ISerialisationClassProvider; -import ua.com.fielden.platform.serialisation.api.impl.ProvidedSerialisationClassProvider; -import ua.com.fielden.platform.test.DbDrivenTestCase; -import ua.com.fielden.platform.test.IDbDrivenTestCaseConfiguration; -import ua.com.fielden.platform.types.Money; - -/** - * Provides a test specific implementation of {@link IDbDrivenTestCaseConfiguration}. - * - * @author TG Team - * - */ -public class PlatformWebDbDrivenTestCaseConfiguration implements IDbDrivenTestCaseConfiguration { - protected final EntityFactory entityFactory; - protected final Injector injector; - protected final HibernateUtil hibernateUtil; - - private final WebHibernateModule hibernateModule; - - public static final Map hibTypeDefaults = new HashMap<>(); - - static { - hibTypeDefaults.put(Date.class, DateTimeType.class); - hibTypeDefaults.put(Money.class, MoneyUserType.class); - } - - private final ISerialisationClassProvider serialisationClassProvider = new ProvidedSerialisationClassProvider(new Class[] { }); - - /** - * Required for dynamic instantiation by {@link DbDrivenTestCase} - */ - public PlatformWebDbDrivenTestCaseConfiguration() { - // instantiate all the factories and Hibernate utility - final ProxyInterceptor interceptor = new ProxyInterceptor(); - try { - - final Configuration cfg = new Configuration(); - final List>> domainTypes = new ArrayList<>(); - domainTypes.add(User.class); - domainTypes.add(UserSecret.class); - domainTypes.add(UserRolesUpdater.class); - domainTypes.add(UserRole.class); - domainTypes.add(UserRoleTokensUpdater.class); - domainTypes.add(SecurityTokenInfo.class); - domainTypes.add(UserAndRoleAssociation.class); - domainTypes.add(UserAndRoleAssociationBatchAction.class); - domainTypes.add(SecurityRoleAssociation.class); - domainTypes.add(SecurityRoleAssociationBatchAction.class); - domainTypes.add(AcknowledgeWarnings.class); - domainTypes.add(PropertyWarning.class); - domainTypes.add(Attachment.class); - final DomainMetadata domainMetadata = new DomainMetadata(hibTypeDefaults, Guice.createInjector(new HibernateUserTypesModule()), domainTypes, DbVersion.H2); - final IdOnlyProxiedEntityTypeCache idOnlyProxiedEntityTypeCache = new IdOnlyProxiedEntityTypeCache(domainMetadata.eqlDomainMetadata); - - try { - cfg.addInputStream(new ByteArrayInputStream(HibernateMappingsGenerator.generateMappings(domainMetadata.eqlDomainMetadata).getBytes("UTF8"))); - } catch (final MappingException | UnsupportedEncodingException e) { - throw new HibernateException("Could not add mappings.", e); - } - - cfg.setProperty("hibernate.current_session_context_class", "thread"); - cfg.setProperty("hibernate.show_sql", "false"); - cfg.setProperty("hibernate.format_sql", "true"); - cfg.setProperty("hibernate.connection.url", "jdbc:h2:./src/test/resources/db/testdb"); - cfg.setProperty("hibernate.connection.driver_class", "org.h2.Driver"); - cfg.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect"); - cfg.setProperty("hibernate.connection.username", "sa"); - cfg.setProperty("hibernate.connection.password", ""); - - hibernateUtil = new HibernateUtil(interceptor, cfg); - hibernateModule = new WebHibernateModule(hibernateUtil.getSessionFactory(), domainMetadata, idOnlyProxiedEntityTypeCache, serialisationClassProvider); - injector = new ApplicationInjectorFactory().add(hibernateModule).getInjector(); - entityFactory = injector.getInstance(EntityFactory.class); - interceptor.setFactory(entityFactory); - } catch (final Exception e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - - @Override - public EntityFactory getEntityFactory() { - return entityFactory; - } - - @Override - public HibernateUtil getHibernateUtil() { - return hibernateUtil; - } - - @Override - public Injector getInjector() { - return injector; - } - - @Override - public List getDdl() { - return null; - } - -} \ No newline at end of file diff --git a/platform-web-resources/src/test/java/ua/com/fielden/web/PlatformWebDrivenTestCaseConfiguration.java b/platform-web-resources/src/test/java/ua/com/fielden/web/PlatformWebDrivenTestCaseConfiguration.java deleted file mode 100644 index f7f707c09b..0000000000 --- a/platform-web-resources/src/test/java/ua/com/fielden/web/PlatformWebDrivenTestCaseConfiguration.java +++ /dev/null @@ -1,49 +0,0 @@ -package ua.com.fielden.web; - -import com.google.inject.Injector; - -import ua.com.fielden.platform.entity.factory.EntityFactory; -import ua.com.fielden.platform.ioc.ApplicationInjectorFactory; -import ua.com.fielden.platform.ioc.NewUserNotifierMockBindingModule; -import ua.com.fielden.platform.serialisation.api.ISerialiser; -import ua.com.fielden.platform.test.IDbDrivenTestCaseConfiguration; -import ua.com.fielden.platform.web.resources.RestServerUtil; -import ua.com.fielden.platform.web.test.IWebDrivenTestCaseConfiguration; - -/** - * A platform specific implementation for web-driven test configuration. - * - * @author TG Team - * - */ -public class PlatformWebDrivenTestCaseConfiguration implements IWebDrivenTestCaseConfiguration { - private final Injector injector; - private final EntityFactory entityFactory; - private RestServerUtil restServerUtil; - - public PlatformWebDrivenTestCaseConfiguration() { - injector = new ApplicationInjectorFactory().add(new NewUserNotifierMockBindingModule()).getInjector(); - entityFactory = injector.getInstance(EntityFactory.class); - } - - @Override - public EntityFactory entityFactory() { - return entityFactory; - } - - @Override - public Injector injector() { - return injector; - } - - @Override - public RestServerUtil restServerUtil() { - return restServerUtil; - } - - @Override - public void setDbDrivenTestConfiguration(final IDbDrivenTestCaseConfiguration config) { - restServerUtil = new RestServerUtil(config.getInjector().getInstance(ISerialiser.class)); - } - -} diff --git a/platform-web-resources/src/test/java/ua/com/fielden/web/domain_driven/authetication/WebResourceGuardTestCase.java b/platform-web-resources/src/test/java/ua/com/fielden/web/domain_driven/authetication/WebResourceGuardTestCase.java index 516a172ed6..b86883c0af 100644 --- a/platform-web-resources/src/test/java/ua/com/fielden/web/domain_driven/authetication/WebResourceGuardTestCase.java +++ b/platform-web-resources/src/test/java/ua/com/fielden/web/domain_driven/authetication/WebResourceGuardTestCase.java @@ -30,7 +30,6 @@ import ua.com.fielden.platform.test_config.AbstractDaoTestCase; import ua.com.fielden.platform.utils.IUniversalConstants; import ua.com.fielden.platform.web.security.AbstractWebResourceGuard; -import ua.com.fielden.platform.web.test.IWebDrivenTestCaseConfiguration; import ua.com.fielden.platform.web.test.WebBasedTestCase; /** @@ -44,7 +43,7 @@ public class WebResourceGuardTestCase extends AbstractDaoTestCase { private final UserSessionDao coSession = (UserSessionDao) co$(UserSession.class); private final UniversalConstantsForTesting constants = (UniversalConstantsForTesting) getInstance(IUniversalConstants.class); private final WebResourceGuardTestWebApplication webApp = getInstance(WebResourceGuardTestWebApplication.class); - private final String baseUri = format("http://localhost:%s/v1", IWebDrivenTestCaseConfiguration.PORT); + private final String baseUri = format("http://localhost:%s/v1", WebBasedTestCase.PORT); private final Client client = new Client(Protocol.HTTP); private IUser coUser = co$(User.class); @@ -302,4 +301,4 @@ public void extractAuthenticator_returns_the_latest_authenticator_if_multiple_au final Optional auth = AbstractWebResourceGuard.extractAuthenticator(request); assertEquals(strAuth2, auth.get().toString()); } -} \ No newline at end of file +} diff --git a/platform-web-resources/src/test/resources/test.properties b/platform-web-resources/src/test/resources/test.properties index 7d7f9e5474..65338fe9c2 100644 --- a/platform-web-resources/src/test/resources/test.properties +++ b/platform-web-resources/src/test/resources/test.properties @@ -1,2 +1 @@ -config = ua.com.fielden.web.PlatformWebDbDrivenTestCaseConfiguration -web-config = ua.com.fielden.web.PlatformWebDrivenTestCaseConfiguration \ No newline at end of file +web-config = ua.com.fielden.web.PlatformWebDrivenTestCaseConfiguration From 465ca335079ffe5062d85298b601840efee044d4 Mon Sep 17 00:00:00 2001 From: homedirectory Date: Fri, 26 Apr 2024 09:22:47 +0300 Subject: [PATCH 02/25] #2244 Remove deprecated Guice modules previously used in DB-driven tests --- .../platform/ioc/CommonFactoryModule.java | 6 +- .../platform/ioc/PropertyFactoryModule.java | 5 - .../platform/ioc/TransactionalModule.java | 12 +- .../test/ioc/DaoTestHibernateModule.java | 198 ------------------ .../com/fielden/web/WebHibernateModule.java | 127 ----------- 5 files changed, 2 insertions(+), 346 deletions(-) delete mode 100644 platform-dao/src/test/java/ua/com/fielden/platform/test/ioc/DaoTestHibernateModule.java delete mode 100644 platform-web-resources/src/test/java/ua/com/fielden/web/WebHibernateModule.java diff --git a/platform-dao/src/main/java/ua/com/fielden/platform/ioc/CommonFactoryModule.java b/platform-dao/src/main/java/ua/com/fielden/platform/ioc/CommonFactoryModule.java index 16e76aa2d2..e5f58b79fe 100644 --- a/platform-dao/src/main/java/ua/com/fielden/platform/ioc/CommonFactoryModule.java +++ b/platform-dao/src/main/java/ua/com/fielden/platform/ioc/CommonFactoryModule.java @@ -23,12 +23,8 @@ public CommonFactoryModule(final Properties props, final Map defau super(props, defaultHibernateTypes, applicationEntityTypes); } - public CommonFactoryModule(final SessionFactory sessionFactory, final DomainMetadata domainMetadata, final IdOnlyProxiedEntityTypeCache idOnlyProxiedEntityTypeCache) { - super(sessionFactory, domainMetadata, idOnlyProxiedEntityTypeCache); - } - protected EntityFactory getEntityFactory() { return entityFactory; } -} \ No newline at end of file +} diff --git a/platform-dao/src/main/java/ua/com/fielden/platform/ioc/PropertyFactoryModule.java b/platform-dao/src/main/java/ua/com/fielden/platform/ioc/PropertyFactoryModule.java index e30b2f5515..6c32966b9c 100644 --- a/platform-dao/src/main/java/ua/com/fielden/platform/ioc/PropertyFactoryModule.java +++ b/platform-dao/src/main/java/ua/com/fielden/platform/ioc/PropertyFactoryModule.java @@ -39,11 +39,6 @@ public PropertyFactoryModule(final Properties props, final Map def initHibernateConfig(entityFactory); } - public PropertyFactoryModule(final SessionFactory sessionFactory, final DomainMetadata domainMetadata, final IdOnlyProxiedEntityTypeCache idOnlyProxiedEntityTypeCache) { - super(sessionFactory, domainMetadata, idOnlyProxiedEntityTypeCache); - entityFactory = new EntityFactory() {}; - } - @Override protected void configure() { super.configure(); diff --git a/platform-dao/src/main/java/ua/com/fielden/platform/ioc/TransactionalModule.java b/platform-dao/src/main/java/ua/com/fielden/platform/ioc/TransactionalModule.java index 0ce95234c5..761524614c 100644 --- a/platform-dao/src/main/java/ua/com/fielden/platform/ioc/TransactionalModule.java +++ b/platform-dao/src/main/java/ua/com/fielden/platform/ioc/TransactionalModule.java @@ -71,16 +71,6 @@ protected void initHibernateConfig(final EntityFactory factory) { interceptor.setFactory(factory); } - public TransactionalModule(final SessionFactory sessionFactory, final DomainMetadata domainMetadata, final IdOnlyProxiedEntityTypeCache idOnlyProxiedEntityTypeCache) { - interceptor = null; - hibernateUtil = null; - applicationEntityTypes = null; - - this.sessionFactory = sessionFactory; - this.domainMetadata = domainMetadata; - this.idOnlyProxiedEntityTypeCache = idOnlyProxiedEntityTypeCache; - } - @Override protected void configure() { super.configure(); @@ -118,4 +108,4 @@ protected List>> getApplicationEntityTypes() { return Collections.unmodifiableList(applicationEntityTypes); } -} \ No newline at end of file +} diff --git a/platform-dao/src/test/java/ua/com/fielden/platform/test/ioc/DaoTestHibernateModule.java b/platform-dao/src/test/java/ua/com/fielden/platform/test/ioc/DaoTestHibernateModule.java deleted file mode 100644 index b4e10c1b95..0000000000 --- a/platform-dao/src/test/java/ua/com/fielden/platform/test/ioc/DaoTestHibernateModule.java +++ /dev/null @@ -1,198 +0,0 @@ -package ua.com.fielden.platform.test.ioc; - -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.SessionFactory; - -import com.google.common.base.Ticker; -import com.google.common.cache.Cache; -import com.google.inject.Scopes; -import com.google.inject.TypeLiteral; - -import ua.com.fielden.platform.dao.EntityWithMoneyDao; -import ua.com.fielden.platform.dao.IEntityDao; -import ua.com.fielden.platform.entity.matcher.IValueMatcherFactory; -import ua.com.fielden.platform.entity.matcher.ValueMatcherFactory; -import ua.com.fielden.platform.entity.query.IdOnlyProxiedEntityTypeCache; -import ua.com.fielden.platform.entity.query.metadata.DomainMetadata; -import ua.com.fielden.platform.error.Result; -import ua.com.fielden.platform.ioc.CommonFactoryModule; -import ua.com.fielden.platform.keygen.IKeyNumber; -import ua.com.fielden.platform.keygen.KeyNumberDao; -import ua.com.fielden.platform.menu.WebMenuItemInvisibilityCo; -import ua.com.fielden.platform.menu.WebMenuItemInvisibilityDao; -import ua.com.fielden.platform.persistence.types.EntityWithMoney; -import ua.com.fielden.platform.sample.domain.ITgCollectionalSerialisationChild; -import ua.com.fielden.platform.sample.domain.ITgCollectionalSerialisationParent; -import ua.com.fielden.platform.sample.domain.ITgMeterReading; -import ua.com.fielden.platform.sample.domain.ITgPublishedYearly; -import ua.com.fielden.platform.sample.domain.ITgTimesheet; -import ua.com.fielden.platform.sample.domain.ITgVehicle; -import ua.com.fielden.platform.sample.domain.ITgVehicleMake; -import ua.com.fielden.platform.sample.domain.ITgVehicleModel; -import ua.com.fielden.platform.sample.domain.ITgWorkOrder; -import ua.com.fielden.platform.sample.domain.TgCollectionalSerialisationChildDao; -import ua.com.fielden.platform.sample.domain.TgCollectionalSerialisationParentDao; -import ua.com.fielden.platform.sample.domain.TgMeterReadingDao; -import ua.com.fielden.platform.sample.domain.TgPublishedYearlyDao; -import ua.com.fielden.platform.sample.domain.TgTimesheetDao; -import ua.com.fielden.platform.sample.domain.TgVehicleDao; -import ua.com.fielden.platform.sample.domain.TgVehicleMakeDao; -import ua.com.fielden.platform.sample.domain.TgVehicleModelDao; -import ua.com.fielden.platform.sample.domain.TgWorkOrderDao; -import ua.com.fielden.platform.security.IAuthorisationModel; -import ua.com.fielden.platform.security.ISecurityToken; -import ua.com.fielden.platform.security.annotations.SessionCache; -import ua.com.fielden.platform.security.annotations.SessionHashingKey; -import ua.com.fielden.platform.security.annotations.TrustedDeviceSessionDuration; -import ua.com.fielden.platform.security.annotations.UntrustedDeviceSessionDuration; -import ua.com.fielden.platform.security.session.IUserSession; -import ua.com.fielden.platform.security.session.UserSession; -import ua.com.fielden.platform.security.session.UserSessionDao; -import ua.com.fielden.platform.security.user.IUser; -import ua.com.fielden.platform.security.user.IUserProvider; -import ua.com.fielden.platform.security.user.SecurityRoleAssociationCo; -import ua.com.fielden.platform.security.user.SecurityRoleAssociationDao; -import ua.com.fielden.platform.security.user.UserAndRoleAssociationCo; -import ua.com.fielden.platform.security.user.UserAndRoleAssociationDao; -import ua.com.fielden.platform.security.user.UserDao; -import ua.com.fielden.platform.security.user.UserRoleCo; -import ua.com.fielden.platform.security.user.UserRoleDao; -import ua.com.fielden.platform.security.user.UserSecretCo; -import ua.com.fielden.platform.security.user.UserSecretDao; -import ua.com.fielden.platform.security.user.impl.ThreadLocalUserProvider; -import ua.com.fielden.platform.serialisation.api.ISerialisationClassProvider; -import ua.com.fielden.platform.serialisation.api.ISerialiser; -import ua.com.fielden.platform.serialisation.api.impl.Serialiser; -import ua.com.fielden.platform.test.domain.entities.daos.BogieDao; -import ua.com.fielden.platform.test.domain.entities.daos.IBogieDao; -import ua.com.fielden.platform.test.domain.entities.daos.IWagonDao; -import ua.com.fielden.platform.test.domain.entities.daos.IWagonSlotDao; -import ua.com.fielden.platform.test.domain.entities.daos.IWorkshopDao; -import ua.com.fielden.platform.test.domain.entities.daos.WagonDao; -import ua.com.fielden.platform.test.domain.entities.daos.WagonSlotDao; -import ua.com.fielden.platform.test.domain.entities.daos.WorkshopDao; -import ua.com.fielden.platform.test.ioc.PlatformTestServerModule.TestSessionCacheBuilder; -import ua.com.fielden.platform.ui.config.EntityCentreAnalysisConfigCo; -import ua.com.fielden.platform.ui.config.EntityCentreAnalysisConfigDao; -import ua.com.fielden.platform.ui.config.EntityCentreConfigCo; -import ua.com.fielden.platform.ui.config.EntityCentreConfigDao; -import ua.com.fielden.platform.ui.config.EntityLocatorConfigCo; -import ua.com.fielden.platform.ui.config.EntityLocatorConfigDao; -import ua.com.fielden.platform.ui.config.EntityMasterConfigCo; -import ua.com.fielden.platform.ui.config.EntityMasterConfigDao; -import ua.com.fielden.platform.ui.config.MainMenuItemCo; -import ua.com.fielden.platform.ui.config.MainMenuItemDao; -import ua.com.fielden.platform.utils.IDates; -import ua.com.fielden.platform.utils.IUniversalConstants; - -/** - * Guice injector module for Hibernate related injections for testing purposes. - * - * @author TG Team - * - */ -public class DaoTestHibernateModule extends CommonFactoryModule { - - public DaoTestHibernateModule(final SessionFactory sessionFactory, final DomainMetadata domainMetadata, final IdOnlyProxiedEntityTypeCache idOnlyProxiedEntityTypeCache) { - super(sessionFactory, domainMetadata, idOnlyProxiedEntityTypeCache); - } - - @Override - protected void configure() { - super.configure(); - // bind DAO - //bind(IFilter.class).to(DataFilter.class); - bind(IKeyNumber.class).to(KeyNumberDao.class); - bind(IBogieDao.class).to(BogieDao.class); - // bind(IWheelsetDao.class).to(WheelsetDao.class); - // bind(IRotableDao.class).to(RotableDao.class); - bind(IWorkshopDao.class).to(WorkshopDao.class); - // bind(IWagonClassDao.class).to(WagonClassDao.class); - // bind(IBogieClassDao.class).to(BogieClassDao.class); - // bind(IWheelsetClassDao.class).to(WheelsetClassDao.class); - bind(IWagonDao.class).to(WagonDao.class); - bind(IWagonSlotDao.class).to(WagonSlotDao.class); - bind(ITgWorkOrder.class).to(TgWorkOrderDao.class); - // bind(IWorkorderableDao.class).to(WorkorderableDao.class); - // bind(IAdviceDao.class).to(AdviceDao.class); - // bind(IRotableClassDao.class).to(RotableClassDao.class); - bind(UserRoleCo.class).to(UserRoleDao.class); - bind(UserAndRoleAssociationCo.class).to(UserAndRoleAssociationDao.class); - bind(SecurityRoleAssociationCo.class).to(SecurityRoleAssociationDao.class); - - bind(IUser.class).to(UserDao.class); - bind(UserSecretCo.class).to(UserSecretDao.class); - // bind IUserProvider - bind(IUserProvider.class).to(ThreadLocalUserProvider.class).in(Scopes.SINGLETON); - - bind(EntityCentreConfigCo.class).to(EntityCentreConfigDao.class); - bind(EntityCentreAnalysisConfigCo.class).to(EntityCentreAnalysisConfigDao.class); - bind(EntityMasterConfigCo.class).to(EntityMasterConfigDao.class); - bind(EntityLocatorConfigCo.class).to(EntityLocatorConfigDao.class); - bind(MainMenuItemCo.class).to(MainMenuItemDao.class); - - bind(WebMenuItemInvisibilityCo.class).to(WebMenuItemInvisibilityDao.class); - - bind(ITgPublishedYearly.class).to(TgPublishedYearlyDao.class); - - bind(ITgTimesheet.class).to(TgTimesheetDao.class); - bind(ITgVehicleModel.class).to(TgVehicleModelDao.class); - bind(ITgVehicleMake.class).to(TgVehicleMakeDao.class); - bind(ITgVehicle.class).to(TgVehicleDao.class); - bind(ITgMeterReading.class).to(TgMeterReadingDao.class); - - bind(IValueMatcherFactory.class).to(ValueMatcherFactory.class).in(Scopes.SINGLETON); - - bind(new TypeLiteral>() { - }).to(EntityWithMoneyDao.class); - - bind(ISerialisationClassProvider.class).toInstance(new ISerialisationClassProvider() { - - @Override - public List> classes() { - return new ArrayList<>(); - } - }); - bind(ISerialiser.class).to(Serialiser.class).in(Scopes.SINGLETON); - - bind(IUserSession.class).to(UserSessionDao.class); - bindConstant().annotatedWith(SessionHashingKey.class).to("This is a hasing key, which is used to hash session data in unit tests."); - bindConstant().annotatedWith(TrustedDeviceSessionDuration.class).to(60 * 24 * 3); // three days - bindConstant().annotatedWith(UntrustedDeviceSessionDuration.class).to(5); // 5 minutes - - bind(Ticker.class).to(TickerForSessionCache.class).in(Scopes.SINGLETON); - bind(IDates.class).to(DatesForTesting.class).in(Scopes.SINGLETON); - bind(IUniversalConstants.class).to(UniversalConstantsForTesting.class).in(Scopes.SINGLETON); - bind(new TypeLiteral>(){}).annotatedWith(SessionCache.class).toProvider(TestSessionCacheBuilder.class).in(Scopes.SINGLETON); - - bind(IAuthorisationModel.class).toInstance(new IAuthorisationModel() { - @Override - public Result authorise(final Class token) { - return Result.successful("always permitted"); - } - - @Override - public void start() { - - } - - @Override - public void stop() { - - } - - @Override - public boolean isStarted() { - return false; - } - - }); - - bind(ITgCollectionalSerialisationParent.class).to(TgCollectionalSerialisationParentDao.class); - bind(ITgCollectionalSerialisationChild.class).to(TgCollectionalSerialisationChildDao.class); - } - - -} diff --git a/platform-web-resources/src/test/java/ua/com/fielden/web/WebHibernateModule.java b/platform-web-resources/src/test/java/ua/com/fielden/web/WebHibernateModule.java deleted file mode 100644 index a0d2c4faf7..0000000000 --- a/platform-web-resources/src/test/java/ua/com/fielden/web/WebHibernateModule.java +++ /dev/null @@ -1,127 +0,0 @@ -package ua.com.fielden.web; - -import org.hibernate.SessionFactory; - -import com.google.common.base.Ticker; -import com.google.common.cache.Cache; -import com.google.inject.Scopes; -import com.google.inject.TypeLiteral; -import com.google.inject.name.Names; - -import ua.com.fielden.platform.attachment.AttachmentDao; -import ua.com.fielden.platform.attachment.IAttachment; -import ua.com.fielden.platform.entity.functional.master.AcknowledgeWarningsCo; -import ua.com.fielden.platform.entity.functional.master.AcknowledgeWarningsDao; -import ua.com.fielden.platform.entity.functional.master.PropertyWarningCo; -import ua.com.fielden.platform.entity.functional.master.PropertyWarningDao; -import ua.com.fielden.platform.entity.query.IdOnlyProxiedEntityTypeCache; -import ua.com.fielden.platform.entity.query.metadata.DomainMetadata; -import ua.com.fielden.platform.ioc.CommonFactoryModule; -import ua.com.fielden.platform.menu.UserMenuVisibilityAssociatorCo; -import ua.com.fielden.platform.menu.UserMenuVisibilityAssociatorDao; -import ua.com.fielden.platform.security.ISecurityRoleAssociationBatchAction; -import ua.com.fielden.platform.security.IUserAndRoleAssociationBatchAction; -import ua.com.fielden.platform.security.SecurityRoleAssociationBatchActionDao; -import ua.com.fielden.platform.security.UserAndRoleAssociationBatchActionDao; -import ua.com.fielden.platform.security.annotations.SessionCache; -import ua.com.fielden.platform.security.annotations.SessionHashingKey; -import ua.com.fielden.platform.security.annotations.TrustedDeviceSessionDuration; -import ua.com.fielden.platform.security.annotations.UntrustedDeviceSessionDuration; -import ua.com.fielden.platform.security.provider.ISecurityTokenController; -import ua.com.fielden.platform.security.provider.SecurityTokenController; -import ua.com.fielden.platform.security.session.IUserSession; -import ua.com.fielden.platform.security.session.UserSession; -import ua.com.fielden.platform.security.session.UserSessionDao; -import ua.com.fielden.platform.security.user.INewUserNotifier; -import ua.com.fielden.platform.security.user.IUser; -import ua.com.fielden.platform.security.user.IUserProvider; -import ua.com.fielden.platform.security.user.SecurityRoleAssociationCo; -import ua.com.fielden.platform.security.user.SecurityRoleAssociationDao; -import ua.com.fielden.platform.security.user.SecurityTokenInfoCo; -import ua.com.fielden.platform.security.user.SecurityTokenInfoDao; -import ua.com.fielden.platform.security.user.UserAndRoleAssociationCo; -import ua.com.fielden.platform.security.user.UserAndRoleAssociationDao; -import ua.com.fielden.platform.security.user.UserDao; -import ua.com.fielden.platform.security.user.UserRoleCo; -import ua.com.fielden.platform.security.user.UserRoleDao; -import ua.com.fielden.platform.security.user.UserRoleTokensUpdaterCo; -import ua.com.fielden.platform.security.user.UserRoleTokensUpdaterDao; -import ua.com.fielden.platform.security.user.UserRolesUpdaterCo; -import ua.com.fielden.platform.security.user.UserRolesUpdaterDao; -import ua.com.fielden.platform.security.user.UserSecretCo; -import ua.com.fielden.platform.security.user.UserSecretDao; -import ua.com.fielden.platform.security.user.impl.ThreadLocalUserProvider; -import ua.com.fielden.platform.serialisation.api.ISerialisationClassProvider; -import ua.com.fielden.platform.serialisation.api.ISerialiser; -import ua.com.fielden.platform.serialisation.api.impl.Serialiser; -import ua.com.fielden.platform.test.ioc.DatesForTesting; -import ua.com.fielden.platform.test.ioc.PlatformTestServerModule.TestSessionCacheBuilder; -import ua.com.fielden.platform.test.ioc.TickerForSessionCache; -import ua.com.fielden.platform.test.ioc.UniversalConstantsForTesting; -import ua.com.fielden.platform.ui.config.EntityCentreConfigCo; -import ua.com.fielden.platform.ui.config.EntityCentreConfigDao; -import ua.com.fielden.platform.ui.config.EntityLocatorConfigCo; -import ua.com.fielden.platform.ui.config.EntityLocatorConfigDao; -import ua.com.fielden.platform.ui.config.EntityMasterConfigCo; -import ua.com.fielden.platform.ui.config.EntityMasterConfigDao; -import ua.com.fielden.platform.utils.IDates; -import ua.com.fielden.platform.utils.IUniversalConstants; - -/** - * Guice injector module for Hibernate related injections, which are specific to testing. - * - * @author TG Team - * - */ -public class WebHibernateModule extends CommonFactoryModule { - private final ISerialisationClassProvider serialisationClassProvider; - - public WebHibernateModule( - final SessionFactory sessionFactory, - final DomainMetadata domainMetadata, - final IdOnlyProxiedEntityTypeCache idOnlyProxiedEntityTypeCache, - final ISerialisationClassProvider serialisationClassProvider - ) { - super(sessionFactory, domainMetadata, idOnlyProxiedEntityTypeCache); - this.serialisationClassProvider = serialisationClassProvider; - } - - @Override - protected void configure() { - super.configure(); - bind(IUserProvider.class).to(ThreadLocalUserProvider.class).in(Scopes.SINGLETON); - bind(INewUserNotifier.class).toInstance(s -> {}); - bind(ISerialisationClassProvider.class).toInstance(serialisationClassProvider); - bind(ISerialiser.class).to(Serialiser.class); - - bind(UserRoleCo.class).to(UserRoleDao.class); - bind(UserRoleTokensUpdaterCo.class).to(UserRoleTokensUpdaterDao.class); - bind(SecurityTokenInfoCo.class).to(SecurityTokenInfoDao.class); - bind(UserAndRoleAssociationCo.class).to(UserAndRoleAssociationDao.class); - bind(SecurityRoleAssociationCo.class).to(SecurityRoleAssociationDao.class); - bind(IUser.class).to(UserDao.class); - bind(UserSecretCo.class).to(UserSecretDao.class); - bind(UserRolesUpdaterCo.class).to(UserRolesUpdaterDao.class); - bind(ISecurityTokenController.class).to(SecurityTokenController.class); - bind(AcknowledgeWarningsCo.class).to(AcknowledgeWarningsDao.class); - bind(PropertyWarningCo.class).to(PropertyWarningDao.class); - bindConstant().annotatedWith(Names.named("attachments.location")).to("."); - bind(IAttachment.class).to(AttachmentDao.class); - bind(IUserAndRoleAssociationBatchAction.class).to(UserAndRoleAssociationBatchActionDao.class); - bind(ISecurityRoleAssociationBatchAction.class).to(SecurityRoleAssociationBatchActionDao.class); - bind(EntityCentreConfigCo.class).to(EntityCentreConfigDao.class); - bind(EntityLocatorConfigCo.class).to(EntityLocatorConfigDao.class); - bind(EntityMasterConfigCo.class).to(EntityMasterConfigDao.class); - bind(IUserSession.class).to(UserSessionDao.class); - bind(UserMenuVisibilityAssociatorCo.class).to(UserMenuVisibilityAssociatorDao.class); - bindConstant().annotatedWith(SessionHashingKey.class).to("This is a hasing key, which is used to hash session data in unit tests."); - bindConstant().annotatedWith(TrustedDeviceSessionDuration.class).to(60 * 24 * 3); // three days - bindConstant().annotatedWith(UntrustedDeviceSessionDuration.class).to(5); // 5 minutes - - bind(Ticker.class).to(TickerForSessionCache.class).in(Scopes.SINGLETON); - bind(IDates.class).to(DatesForTesting.class).in(Scopes.SINGLETON); - bind(IUniversalConstants.class).to(UniversalConstantsForTesting.class).in(Scopes.SINGLETON); - bind(new TypeLiteral>(){}).annotatedWith(SessionCache.class).toProvider(TestSessionCacheBuilder.class).in(Scopes.SINGLETON); - } - -} \ No newline at end of file From 7fe46f8504104a685efdc16fcfc392e3e2e78ac3 Mon Sep 17 00:00:00 2001 From: homedirectory Date: Fri, 26 Apr 2024 09:31:28 +0300 Subject: [PATCH 03/25] #2244 Refactor obsolete WebBasedTestCase into a static test utility to better reflect its purpose --- .../platform/web/test/TestWebApplication.java | 66 ++++++++++++++++ .../platform/web/test/WebBasedTestCase.java | 76 ------------------- .../WebResourceGuardTestCase.java | 8 +- 3 files changed, 70 insertions(+), 80 deletions(-) create mode 100644 platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/TestWebApplication.java delete mode 100644 platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/WebBasedTestCase.java diff --git a/platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/TestWebApplication.java b/platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/TestWebApplication.java new file mode 100644 index 0000000000..0c9631bdf0 --- /dev/null +++ b/platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/TestWebApplication.java @@ -0,0 +1,66 @@ +package ua.com.fielden.platform.web.test; + +import org.apache.logging.log4j.Logger; +import org.restlet.Component; +import org.restlet.Restlet; +import org.restlet.data.Protocol; + +import static org.apache.logging.log4j.LogManager.getLogger; + +/** + * Restlet application that can be used in tests. + *

+ * This class can be used statically for attaching/detaching restlets from the running server via: + *

    + *
  • {@link #attachWebApplication(String, Restlet)} + *
  • {@link #detachWebApplication(Restlet)} + *
+ *

+ * WebAppliction in the name of these method refers to a test web application, which should incorporate the routing for all its web resources. + *

+ * + * @author TG Team + */ +public final class TestWebApplication { + + private static final Logger LOGGER = getLogger(TestWebApplication.class); + public static final int PORT = 9042; + static final Component component = new Component(); + + static { + component.getServers().add(Protocol.HTTP, PORT); + try { + component.start(); + } catch (final Exception e) { + LOGGER.error("Failed to start the test web component.", e); + } + } + + /** + * Attaches the provided restlet to the running server at the specified path prefix. + */ + public static void attachWebApplication(final String pathPrefix, final Restlet restlet) { + try { + component.getDefaultHost().attach(pathPrefix, restlet); + } catch (final Exception e) { + LOGGER.fatal("Failed to attach web application.", e); + System.exit(100); + } + + } + + /** + * Removes web application with all its routes from the test web server. + */ + public static void detachWebApplication(final Restlet restlet) { + try { + component.getDefaultHost().detach(restlet); + } catch (final Exception e) { + LOGGER.fatal("Failed to detach web application.", e); + System.exit(100); + } + } + + private TestWebApplication() {} + +} diff --git a/platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/WebBasedTestCase.java b/platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/WebBasedTestCase.java deleted file mode 100644 index 21b286c406..0000000000 --- a/platform-web-resources/src/test/java/ua/com/fielden/platform/web/test/WebBasedTestCase.java +++ /dev/null @@ -1,76 +0,0 @@ -package ua.com.fielden.platform.web.test; - -import org.restlet.Application; -import org.restlet.Component; -import org.restlet.Restlet; -import org.restlet.data.Protocol; - -/** - * This is a base class for web-driven testing of resources and RAOs. It is responsible for auto-configuration of a web-server listening on port 9000. - *

- * Descendants of this class should implement method {@link #getDataSetPaths()} similarly as for {@link DbDrivenTestCase}. - *

- * WebBasedTestCase is also a restlet application. The web resources that need to be tested or used for testing should be bound by overriding method {@link Application#getRoot()}. - *

- * An instance of pre-configured {@link RestClientUtil} is provided for the use by descendants requiring instantiation of RAO classes. - *

- * Effectively each web-drive test case is a little web-application. - *

- *


- *
- * As of recently this class can also be used statically for attaching/detaching restlets from the running server. - * This provides a way to reuse the current unit test server not only by extending the class, but also by means of directly - * interacting with the unit test server, which is established statically and is the same for all test case instances, - * by means of methods {@link WebBasedTestCase#attachWebApplication(Restlet)} and {@link WebBasedTestCase#detachWebApplication(Restlet)}. - *

- * The term WebAppliction in the name of these method refers to a test web application, which should incorporate the routing for all its web resources. - *

- * Since the move to domain driven testing where all data is populated through the domain, there is no really any - * practical reason to extend {@link WebBasedTestCase}. - * - * @author TG Team - * - */ -public abstract class WebBasedTestCase { - protected static final Component component = new Component(); - public static final int PORT = 9042; - static { - component.getServers().add(Protocol.HTTP, PORT); - try { - component.start(); - } catch (final Exception e) { - System.out.println("Failed to start the test web component:"); - e.printStackTrace(); - } - } - - /** - * Attaches the provided restlet to the running server at the specified path prefix. - * - * @param restlet - */ - public static void attachWebApplication(final String pathPrefix, final Restlet restlet) { - try { - component.getDefaultHost().attach(pathPrefix, restlet); - } catch (final Exception e) { - e.printStackTrace(); - System.exit(100); - } - - } - - /** - * Removes web application with all its routes from the test web server. - * - * @param restlet - */ - public static void detachWebApplication(final Restlet restlet) { - try { - component.getDefaultHost().detach(restlet); - } catch (final Exception e) { - e.printStackTrace(); - System.exit(100); - } - } - -} diff --git a/platform-web-resources/src/test/java/ua/com/fielden/web/domain_driven/authetication/WebResourceGuardTestCase.java b/platform-web-resources/src/test/java/ua/com/fielden/web/domain_driven/authetication/WebResourceGuardTestCase.java index b86883c0af..ac9aea39b6 100644 --- a/platform-web-resources/src/test/java/ua/com/fielden/web/domain_driven/authetication/WebResourceGuardTestCase.java +++ b/platform-web-resources/src/test/java/ua/com/fielden/web/domain_driven/authetication/WebResourceGuardTestCase.java @@ -30,7 +30,7 @@ import ua.com.fielden.platform.test_config.AbstractDaoTestCase; import ua.com.fielden.platform.utils.IUniversalConstants; import ua.com.fielden.platform.web.security.AbstractWebResourceGuard; -import ua.com.fielden.platform.web.test.WebBasedTestCase; +import ua.com.fielden.platform.web.test.TestWebApplication; /** * A test case to ensure correct HTTP responses (HTTP codes and cookies) to requests for accessing guarded web resources. @@ -43,7 +43,7 @@ public class WebResourceGuardTestCase extends AbstractDaoTestCase { private final UserSessionDao coSession = (UserSessionDao) co$(UserSession.class); private final UniversalConstantsForTesting constants = (UniversalConstantsForTesting) getInstance(IUniversalConstants.class); private final WebResourceGuardTestWebApplication webApp = getInstance(WebResourceGuardTestWebApplication.class); - private final String baseUri = format("http://localhost:%s/v1", WebBasedTestCase.PORT); + private final String baseUri = format("http://localhost:%s/v1", TestWebApplication.PORT); private final Client client = new Client(Protocol.HTTP); private IUser coUser = co$(User.class); @@ -51,12 +51,12 @@ public class WebResourceGuardTestCase extends AbstractDaoTestCase { public void startUp() { coSession.getCache().invalidateAll(); webApp.setCurrUser(coUser.findByKey(User.system_users.UNIT_TEST_USER.name())); - WebBasedTestCase.attachWebApplication("/v1", webApp); + TestWebApplication.attachWebApplication("/v1", webApp); } @After public void tearDown() { - WebBasedTestCase.detachWebApplication(webApp); + TestWebApplication.detachWebApplication(webApp); } @Test From 5422c45c8e450cf8b0dd47cf0ab05f605a5bf651 Mon Sep 17 00:00:00 2001 From: 01es Date: Mon, 29 Apr 2024 15:44:24 +1000 Subject: [PATCH 04/25] #2247 Implemented issue requirements. --- .../fielden/platform/utils/EntityUtils.java | 160 ++++++++---------- .../platform/utils/EntityUtilsTest.java | 107 +++++------- 2 files changed, 118 insertions(+), 149 deletions(-) diff --git a/platform-pojo-bl/src/main/java/ua/com/fielden/platform/utils/EntityUtils.java b/platform-pojo-bl/src/main/java/ua/com/fielden/platform/utils/EntityUtils.java index d499acc503..8fa658d67e 100644 --- a/platform-pojo-bl/src/main/java/ua/com/fielden/platform/utils/EntityUtils.java +++ b/platform-pojo-bl/src/main/java/ua/com/fielden/platform/utils/EntityUtils.java @@ -1,76 +1,15 @@ package ua.com.fielden.platform.utils; -import static java.lang.String.format; -import static java.lang.reflect.Modifier.isStatic; -import static java.util.Arrays.stream; -import static java.util.Optional.ofNullable; -import static java.util.stream.Stream.concat; -import static java.util.stream.Stream.empty; -import static java.util.stream.Stream.of; -import static org.apache.commons.lang3.StringUtils.isEmpty; -import static org.apache.commons.lang3.StringUtils.lastIndexOf; -import static org.apache.commons.lang3.StringUtils.length; -import static org.apache.logging.log4j.LogManager.getLogger; -import static ua.com.fielden.platform.entity.AbstractEntity.ID; -import static ua.com.fielden.platform.entity.AbstractEntity.KEY; -import static ua.com.fielden.platform.entity.AbstractEntity.VERSION; -import static ua.com.fielden.platform.entity.fetch.FetchProviderFactory.createDefaultFetchProvider; -import static ua.com.fielden.platform.entity.fetch.FetchProviderFactory.createEmptyFetchProvider; -import static ua.com.fielden.platform.entity.fetch.FetchProviderFactory.createFetchProviderWithKeyAndDesc; -import static ua.com.fielden.platform.reflection.AnnotationReflector.getKeyType; -import static ua.com.fielden.platform.reflection.AnnotationReflector.isAnnotationPresent; -import static ua.com.fielden.platform.reflection.Finder.findFieldByName; -import static ua.com.fielden.platform.reflection.Finder.getKeyMembers; -import static ua.com.fielden.platform.reflection.PropertyTypeDeterminator.PROPERTY_SPLITTER; -import static ua.com.fielden.platform.reflection.PropertyTypeDeterminator.determinePropertyType; -import static ua.com.fielden.platform.types.tuples.T2.t2; -import static ua.com.fielden.platform.utils.StreamUtils.takeWhile; -import static ua.com.fielden.platform.web.centre.WebApiUtils.dslName; - -import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; -import java.text.DateFormat; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.apache.logging.log4j.Logger; -import org.joda.time.DateTime; - import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; - +import org.apache.logging.log4j.Logger; +import org.joda.time.DateTime; import ua.com.fielden.platform.companion.IEntityReader; import ua.com.fielden.platform.entity.AbstractEntity; import ua.com.fielden.platform.entity.AbstractUnionEntity; import ua.com.fielden.platform.entity.ActivatableAbstractEntity; import ua.com.fielden.platform.entity.DynamicEntityKey; -import ua.com.fielden.platform.entity.annotation.DateOnly; -import ua.com.fielden.platform.entity.annotation.DenyIntrospection; -import ua.com.fielden.platform.entity.annotation.DescTitle; -import ua.com.fielden.platform.entity.annotation.IsProperty; -import ua.com.fielden.platform.entity.annotation.KeyType; -import ua.com.fielden.platform.entity.annotation.MapEntityTo; +import ua.com.fielden.platform.entity.annotation.*; import ua.com.fielden.platform.entity.fetch.IFetchProvider; import ua.com.fielden.platform.entity.meta.MetaProperty; import ua.com.fielden.platform.entity.meta.PropertyDescriptor; @@ -92,6 +31,41 @@ import ua.com.fielden.platform.types.try_wrapper.TryWrapper; import ua.com.fielden.platform.types.tuples.T2; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; +import java.text.DateFormat; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.util.Optional; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.lang.String.format; +import static java.lang.reflect.Modifier.isStatic; +import static java.util.Arrays.stream; +import static java.util.stream.Stream.concat; +import static java.util.stream.Stream.of; +import static org.apache.commons.lang3.StringUtils.*; +import static org.apache.logging.log4j.LogManager.getLogger; +import static ua.com.fielden.platform.entity.AbstractEntity.*; +import static ua.com.fielden.platform.entity.fetch.FetchProviderFactory.*; +import static ua.com.fielden.platform.reflection.AnnotationReflector.getKeyType; +import static ua.com.fielden.platform.reflection.AnnotationReflector.isAnnotationPresent; +import static ua.com.fielden.platform.reflection.Finder.findFieldByName; +import static ua.com.fielden.platform.reflection.Finder.getKeyMembers; +import static ua.com.fielden.platform.reflection.PropertyTypeDeterminator.PROPERTY_SPLITTER; +import static ua.com.fielden.platform.reflection.PropertyTypeDeterminator.determinePropertyType; +import static ua.com.fielden.platform.types.tuples.T2.t2; +import static ua.com.fielden.platform.utils.StreamUtils.takeWhile; +import static ua.com.fielden.platform.web.centre.WebApiUtils.dslName; + public class EntityUtils { private static final Logger logger = getLogger(EntityUtils.class); @@ -191,8 +165,8 @@ public static A coalesce(final A value, final A alternative, final A... othe /** * Null-safe comparator. * - * @param o1 - * @param o2 + * @param c1 + * @param c2 * @return */ public static int safeCompare(final Comparable c1, final T c2) { @@ -241,7 +215,7 @@ public static , K extends Comparable> int compare(fi /** - * Returns value that indicates whether entity is among entities. The equality comparison is based on {@link #areEquals(AbstractEntity, AbstractEntity)} method + * Returns value that indicates whether entity is among entities. The equality comparison is based on {@link #areEqual(AbstractEntity, AbstractEntity)} method * * @param entities * @param entity @@ -257,7 +231,7 @@ public static > boolean containsById(final List e } /** - * Returns index of the entity in the entities list. The equality comparison is based on the {@link #areEquals(AbstractEntity, AbstractEntity)} method. + * Returns index of the entity in the entities list. The equality comparison is based on the {@link #areEqual(AbstractEntity, AbstractEntity)} method. * * @param entities * @param entity @@ -393,12 +367,11 @@ public static MetaProperty findFirstFailedMetaProperty(final List startProperty, final MetaProperty finishProperty, final boolean finishSetter, final IDates dates) { @@ -419,14 +392,13 @@ public static void validateDateRange(final Date start, final Date finish, final } /** - * This method throws Result (so can be used to specify DYNAMIC validation inside the date setters) when the specified finish/start date times are invalid together. + * This method throws {@link Result} when the specified finish/start date times are invalid together. * * @param start * @param finish - * @param fieldPrefix - * - the prefix for the field in the error message for e.g. "actual" or "early". - * @param finishSetter - * - use true if validation have to be performed inside the "finish" date setter, false - inside the "start" date setter + * @param startProperty a property representing the start of a range. + * @param finishProperty a property representing the finish of a range. + * @param finishSetter specify {@code true} if validation has to be performed for the finish property, {@code false} - for the start property. * @throws Result */ public static void validateDateTimeRange(final DateTime start, final DateTime finish, final MetaProperty startProperty, final MetaProperty finishProperty, final boolean finishSetter, final IDates dates) { @@ -684,6 +656,24 @@ public static boolean isPersistedEntityType(final Class type) { } } + /** + * Returns the first persistent entity type of the type hierarchy for {@code entityType}. This could be {@code entityType} itself or the first super type that represents a persistent entity. + * Otherwise, an empty result is returned. + * + * @param entityType + * @return + */ + public static Optional>> findFirstPersistentTypeInHierarchyFor(final Class> entityType) { + Class type = entityType; + while (type != AbstractEntity.class) { + if (isPersistedEntityType(type)) { + return Optional.of((Class>) type); + } + type = type.getSuperclass(); + } + return Optional.empty(); + } + /** * Determines whether the provided entity type is of synthetic nature, which means that is based on an EQL model. * @@ -731,7 +721,7 @@ public static > Field findSyntheticModelFieldFor(fin /** * Determines whether the provided entity type is of synthetic nature that at the same time is based on a persistent type. - * This kind of entities most typically should have a model with yieldAll clause. + * This kind of entity most typically should have a model with yieldAll clause. * * @param type * @return @@ -1041,8 +1031,8 @@ public static boolean isConflicting(final Object staleNewValue, final Object sta * @param instrumented * @return */ - public static > IFetchProvider fetch(final Class entityType, final boolean instumented) { - return createDefaultFetchProvider(entityType, instumented); + public static > IFetchProvider fetch(final Class entityType, final boolean instrumented) { + return createDefaultFetchProvider(entityType, instrumented); } public static > IFetchProvider fetch(final Class entityType) { @@ -1242,9 +1232,9 @@ public static > Optional fetchEntityForPropOf(fin * final PmRoutine pmRoutine = EntityUtils.fetchEntityForPropOf(pmId, "pmRoutine", co(PmExpendable.class)).orElseThrow(...); * * + * @param id * @param propName * @param coOther - * @param keyValues * @return */ public static > Optional fetchEntityForPropOf(final Long id, final String propName, final IEntityReader coOther) { @@ -1265,9 +1255,9 @@ public static > Optional fetchEntityForPropOf(fin * final PmRoutine freshPmRoutine = EntityUtils.fetchEntityForPropOf(stalePmRoutine, "pmRoutine", co(PmExpendable.class)).orElseThrow(...); * * + * @param instance * @param propName * @param coOther - * @param keyValues * @return */ public static > Optional fetchEntityForPropOf(final T instance, final String propName, final IEntityReader coOther) { @@ -1304,7 +1294,7 @@ public static > Optional findByIdWithMasterFetch( * However, if the resultant entity to be mutated then argument {@code co} must correspond to an instrumenting instance. * * @param co -- either pure reader or mutator if the resultant entity needs to be changed - * @param kayValues -- an array of values for entity key members + * @param keyValues -- an array of values for entity key members * @return */ public static > Optional findByKeyWithMasterFetch(final IEntityReader co, final Object... keyValues) { diff --git a/platform-pojo-bl/src/test/java/ua/com/fielden/platform/utils/EntityUtilsTest.java b/platform-pojo-bl/src/test/java/ua/com/fielden/platform/utils/EntityUtilsTest.java index f2dd3bbef2..96edc8e407 100644 --- a/platform-pojo-bl/src/test/java/ua/com/fielden/platform/utils/EntityUtilsTest.java +++ b/platform-pojo-bl/src/test/java/ua/com/fielden/platform/utils/EntityUtilsTest.java @@ -1,63 +1,17 @@ package ua.com.fielden.platform.utils; -import static java.math.RoundingMode.HALF_EVEN; -import static java.util.stream.Collectors.toCollection; -import static java.util.stream.Collectors.toList; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static ua.com.fielden.platform.entity.AbstractEntity.DESC; -import static ua.com.fielden.platform.entity.AbstractEntity.ID; -import static ua.com.fielden.platform.entity.AbstractEntity.VERSION; -import static ua.com.fielden.platform.reflection.asm.impl.DynamicEntityClassLoader.startModification; -import static ua.com.fielden.platform.utils.CollectionUtil.linkedSetOf; -import static ua.com.fielden.platform.utils.CollectionUtil.listOf; -import static ua.com.fielden.platform.utils.EntityUtils.coalesce; -import static ua.com.fielden.platform.utils.EntityUtils.equalsEx; -import static ua.com.fielden.platform.utils.EntityUtils.getCollectionalProperties; -import static ua.com.fielden.platform.utils.EntityUtils.isIntrospectionDenied; -import static ua.com.fielden.platform.utils.EntityUtils.isNaturalOrderDescending; -import static ua.com.fielden.platform.utils.EntityUtils.isPersistedEntityType; -import static ua.com.fielden.platform.utils.EntityUtils.isSyntheticBasedOnPersistentEntityType; -import static ua.com.fielden.platform.utils.EntityUtils.isSyntheticEntityType; -import static ua.com.fielden.platform.utils.EntityUtils.isUnionEntityType; -import static ua.com.fielden.platform.utils.EntityUtils.keyPaths; -import static ua.com.fielden.platform.utils.EntityUtils.safeCompare; -import static ua.com.fielden.platform.utils.EntityUtils.toDecimal; - -import java.lang.reflect.Field; -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; -import java.sql.Timestamp; -import java.util.Date; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.ThreadLocalRandom; -import java.util.stream.Stream; - +import com.google.inject.Injector; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.junit.Test; - -import com.google.inject.Injector; - import ua.com.fielden.platform.attachment.Attachment; import ua.com.fielden.platform.dashboard.DashboardRefreshFrequency; import ua.com.fielden.platform.dashboard.DashboardRefreshFrequencyUnit; import ua.com.fielden.platform.domain.PlatformDomainTypes; import ua.com.fielden.platform.domain.metadata.DomainExplorer; -import ua.com.fielden.platform.entity.AbstractEntity; -import ua.com.fielden.platform.entity.ChildEntity; -import ua.com.fielden.platform.entity.Entity; -import ua.com.fielden.platform.entity.EntityExt; +import ua.com.fielden.platform.entity.*; import ua.com.fielden.platform.entity.annotation.Calculated; -import ua.com.fielden.platform.entity.UserDefinableHelp; import ua.com.fielden.platform.entity.annotation.IsProperty; import ua.com.fielden.platform.entity.annotation.factory.CalculatedAnnotation; import ua.com.fielden.platform.entity.factory.EntityFactory; @@ -65,27 +19,32 @@ import ua.com.fielden.platform.keygen.KeyNumber; import ua.com.fielden.platform.reflection.AnnotationReflector; import ua.com.fielden.platform.reflection.asm.api.NewProperty; -import ua.com.fielden.platform.sample.domain.TgAuthor; -import ua.com.fielden.platform.sample.domain.TgAverageFuelUsage; -import ua.com.fielden.platform.sample.domain.TgMeterReading; -import ua.com.fielden.platform.sample.domain.TgOrgUnit2; -import ua.com.fielden.platform.sample.domain.TgOrgUnit3; -import ua.com.fielden.platform.sample.domain.TgOrgUnit4; -import ua.com.fielden.platform.sample.domain.TgOrgUnit5; -import ua.com.fielden.platform.sample.domain.TgReVehicleModel; -import ua.com.fielden.platform.sample.domain.TgVehicle; -import ua.com.fielden.platform.sample.domain.TgVehicleFinDetails; -import ua.com.fielden.platform.sample.domain.UnionEntity; -import ua.com.fielden.platform.security.user.ReUser; -import ua.com.fielden.platform.security.user.SecurityRoleAssociation; -import ua.com.fielden.platform.security.user.User; -import ua.com.fielden.platform.security.user.UserAndRoleAssociation; -import ua.com.fielden.platform.security.user.UserRole; +import ua.com.fielden.platform.sample.domain.*; +import ua.com.fielden.platform.security.user.*; import ua.com.fielden.platform.test.CommonTestEntityModuleWithPropertyFactory; import ua.com.fielden.platform.test.EntityModuleWithPropertyFactory; import ua.com.fielden.platform.types.Money; import ua.com.fielden.platform.types.tuples.T2; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; +import java.sql.Timestamp; +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Stream; + +import static java.math.RoundingMode.HALF_EVEN; +import static java.util.stream.Collectors.toCollection; +import static java.util.stream.Collectors.toList; +import static org.junit.Assert.*; +import static ua.com.fielden.platform.entity.AbstractEntity.*; +import static ua.com.fielden.platform.reflection.asm.impl.DynamicEntityClassLoader.startModification; +import static ua.com.fielden.platform.utils.CollectionUtil.linkedSetOf; +import static ua.com.fielden.platform.utils.CollectionUtil.listOf; +import static ua.com.fielden.platform.utils.EntityUtils.*; + public class EntityUtilsTest { private final EntityModuleWithPropertyFactory module = new CommonTestEntityModuleWithPropertyFactory(); private final Injector injector = new ApplicationInjectorFactory().add(module).getInjector(); @@ -682,6 +641,26 @@ public void only_a_specific_subset_of_platform_level_entities_have_introspection assertEquals(expected, filtered); } + @Test + public void findFirstPersistentTypeInHierarchyFor_a_persistent_type_returns_that_type() { + final var maybePersistentType = EntityUtils.findFirstPersistentTypeInHierarchyFor(Attachment.class); + assertTrue(maybePersistentType.isPresent()); + assertEquals(Attachment.class , maybePersistentType.get()); + } + + @Test + public void findFirstPersistentTypeInHierarchyFor_a_synthetic_entity_based_on_persistent_type_returns_that_type() { + final var maybePersistentType = EntityUtils.findFirstPersistentTypeInHierarchyFor(TgReVehicleModel.class); + assertTrue(maybePersistentType.isPresent()); + assertEquals(TgVehicleModel.class , maybePersistentType.get()); + } + + @Test + public void findFirstPersistentTypeInHierarchyFor_an_entity_with_no_persistent_type_in_its_hierarhcy_returns_empty_result() { + final var maybePersistentType = EntityUtils.findFirstPersistentTypeInHierarchyFor(Entity.class); + assertFalse(maybePersistentType.isPresent()); + } + /** * A helper factory method for generating a new type based on {@code baseType} with the {@code maxNestedLevels} of nesting (i.e., a new type gets generated based on the previously generated type sequentially). * From b7cf3e3dad1bdad88ba378b5869261e07346c510 Mon Sep 17 00:00:00 2001 From: 01es Date: Mon, 29 Apr 2024 16:05:59 +1000 Subject: [PATCH 05/25] #2247 Corrected imports that were damanged by IDEA somewhow. --- .../main/java/ua/com/fielden/platform/utils/EntityUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform-pojo-bl/src/main/java/ua/com/fielden/platform/utils/EntityUtils.java b/platform-pojo-bl/src/main/java/ua/com/fielden/platform/utils/EntityUtils.java index 8fa658d67e..c6d209a08c 100644 --- a/platform-pojo-bl/src/main/java/ua/com/fielden/platform/utils/EntityUtils.java +++ b/platform-pojo-bl/src/main/java/ua/com/fielden/platform/utils/EntityUtils.java @@ -50,8 +50,8 @@ import static java.lang.String.format; import static java.lang.reflect.Modifier.isStatic; import static java.util.Arrays.stream; -import static java.util.stream.Stream.concat; -import static java.util.stream.Stream.of; +import static java.util.Optional.ofNullable; +import static java.util.stream.Stream.*; import static org.apache.commons.lang3.StringUtils.*; import static org.apache.logging.log4j.LogManager.getLogger; import static ua.com.fielden.platform.entity.AbstractEntity.*; From 4a65b6ac627d9aa89eded757ae8a7c169f4ceeef Mon Sep 17 00:00:00 2001 From: 01es Date: Wed, 1 May 2024 22:46:44 +1000 Subject: [PATCH 06/25] #2248 Implemented issue requirements. --- .../platform/entity/AbstractUnionEntity.java | 94 ++++++--- .../ioc/ObservableMutatorInterceptor.java | 23 +-- .../platform/entity/AbstractEntityTest.java | 70 ++----- .../entity/union/AbstractUnionEntityTest.java | 190 ++++++++++++------ .../union/UnionEntityWithKindOneError.java | 6 + .../union/UnionEntityWithKindTwoError.java | 5 + 6 files changed, 230 insertions(+), 158 deletions(-) diff --git a/platform-pojo-bl/src/main/java/ua/com/fielden/platform/entity/AbstractUnionEntity.java b/platform-pojo-bl/src/main/java/ua/com/fielden/platform/entity/AbstractUnionEntity.java index 3769dca588..bc7d674cb9 100644 --- a/platform-pojo-bl/src/main/java/ua/com/fielden/platform/entity/AbstractUnionEntity.java +++ b/platform-pojo-bl/src/main/java/ua/com/fielden/platform/entity/AbstractUnionEntity.java @@ -1,26 +1,28 @@ package ua.com.fielden.platform.entity; -import static java.lang.String.format; -import static java.util.Optional.ofNullable; -import static ua.com.fielden.platform.reflection.Finder.findRealProperties; -import static ua.com.fielden.platform.utils.EntityUtils.equalsEx; +import ua.com.fielden.platform.entity.annotation.KeyType; +import ua.com.fielden.platform.entity.annotation.Observable; +import ua.com.fielden.platform.entity.exceptions.EntityDefinitionException; +import ua.com.fielden.platform.entity.exceptions.EntityException; +import ua.com.fielden.platform.entity.factory.IMetaPropertyFactory; +import ua.com.fielden.platform.reflection.Finder; +import ua.com.fielden.platform.reflection.Reflector; +import ua.com.fielden.platform.reflection.exceptions.ReflectionException; +import javax.annotation.Nonnull; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.Stream; -import org.apache.commons.lang3.StringUtils; - -import ua.com.fielden.platform.entity.annotation.KeyType; -import ua.com.fielden.platform.entity.annotation.Observable; -import ua.com.fielden.platform.entity.exceptions.EntityException; -import ua.com.fielden.platform.entity.factory.IMetaPropertyFactory; -import ua.com.fielden.platform.reflection.Finder; -import ua.com.fielden.platform.reflection.Reflector; -import ua.com.fielden.platform.reflection.exceptions.ReflectionException; +import static java.util.Optional.ofNullable; +import static org.apache.commons.lang3.StringUtils.isEmpty; +import static ua.com.fielden.platform.reflection.Finder.findRealProperties; +import static ua.com.fielden.platform.reflection.Finder.streamRealProperties; +import static ua.com.fielden.platform.utils.EntityUtils.equalsEx; /** * A base class for implementing synthetic entities to be used for modelling situations where a property of some entity can be of multiple types, but any individual instance of a @@ -34,16 +36,20 @@ */ @KeyType(String.class) public abstract class AbstractUnionEntity extends AbstractEntity { + + public static final String ERR_UNION_PROPERTY_ALREADY_HAS_VALUE = "Invalid attempt to set property [%s] as active for union entity [%s] with active property [%s]."; + public static final String ERR_ACTIVE_PROPERTY_NOT_DETERMINED = "Active property for union entity [%s] has not been determined."; + /** Points out the name of a non-null property. */ private String activePropertyName; /** - * Enforces union rule -- only one property can be set and only once from the time of union entity instantiation. Such property drives values for properties id, - * key and desc. + * Enforces union rule: only one property can be set and only once from the moment of union entity instantiation. + * Such property drives values for properties {@code id}, {@code key} and {@code desc}. */ public final void ensureUnion(final String propertyName) { - if (!StringUtils.isEmpty(activePropertyName)) { - throw new EntityException(format("Invalid attempt to set property [%s] as active for union entity [%s] that already has property [%s] identified as active.", propertyName, getType().getName(), activePropertyName)); + if (!isEmpty(activePropertyName)) { + throw new EntityException(ERR_UNION_PROPERTY_ALREADY_HAS_VALUE.formatted(propertyName, getType().getSimpleName(), activePropertyName)); } activePropertyName = propertyName; } @@ -89,10 +95,10 @@ public AbstractUnionEntity setDesc(final String desc) { } private void ensureActiveProperty() { - if (StringUtils.isEmpty(activePropertyName)) { + if (isEmpty(activePropertyName)) { activePropertyName = getNameOfAssignedUnionProperty(); - if (StringUtils.isEmpty(activePropertyName)) { - throw new EntityException(format("Active property for union entity [%s] has not been determined.", getType().getName())); + if (isEmpty(activePropertyName)) { + throw new EntityException(ERR_ACTIVE_PROPERTY_NOT_DETERMINED.formatted(getType().getSimpleName())); } } } @@ -114,11 +120,11 @@ protected final void setMetaPropertyFactory(final IMetaPropertyFactory metaPrope for (final Field field : fields) { // union entities should not have properties that are not of entity type if (!AbstractEntity.class.isAssignableFrom(field.getType())) { - throw new IllegalStateException("Union entity should not contain properties of ordinary type."); // kind one error + throw new EntityDefinitionException("Union entity should not contain properties of ordinary type. Check property [%s].".formatted(field.getName())); // kind one error } // union properties should not contain more than one property of a certain entity type if (propertyTypes.contains(field.getType())) { - throw new IllegalStateException("Union entity should contain only properties of unique types."); // kind two error + throw new EntityDefinitionException("Union entity should contain only properties of unique types. Check property [%s].".formatted(field.getName())); // kind two error } propertyTypes.add((Class>) field.getType()); } @@ -147,7 +153,7 @@ private String getNameOfAssignedUnionProperty() { * @return */ public final AbstractEntity activeEntity() { - final Stream propertyNames = Finder.streamRealProperties(getType()).map(Field::getName); + final Stream propertyNames = streamRealProperties(getType()).map(Field::getName); return propertyNames .filter(propName -> !Reflector.isPropertyProxied(this, propName) && get(propName) != null) @@ -156,11 +162,41 @@ public final AbstractEntity activeEntity() { .orElse(null); // return the property value or null if there was no matching propName } + /** + * A convenient method for setting a union property to a non-null value. + * It should only be used on union entity instances that do not yet have an active union-property. + *

+ * This method looks for an appropriate union-property based on the type of {@code value}, which gets assigned to that property. + * If no appropriate union-property is found, exception {@link EntityException} is thrown. + * + * @param value a non-null value + * @return an instance of this union entity + * @param a type of the union entity as a convenience for method chaining + */ + public final T setUnionProperty(@Nonnull final AbstractEntity value) { + // If null is being assigned then we only need to clear the active union property, if it exists. + if (value == null) { + throw new EntityException("Null is not a valid value for union-properties (union entity [%s]).".formatted(getType().getSimpleName())); + } + // A non-null value can only be assigned if it matches one of the union properties by type. + final Optional maybeMatchingProp = streamRealProperties(getType()).filter(field -> field.getType().equals(value.getType())).findFirst(); + if (maybeMatchingProp.isPresent()) { + final String propertyName = maybeMatchingProp.get().getName(); + if (!isEmpty(activePropertyName)) { + throw new EntityException(ERR_UNION_PROPERTY_ALREADY_HAS_VALUE.formatted(propertyName, getType().getSimpleName(), activePropertyName)); + } + // property setter should be used to trigger the assignment logic + this.set(propertyName, value); + return (T) this; + } + // If no matching union property is found, we throw an exception. + throw new EntityException("None of the union properties match type [%s].".formatted(value.getType().getSimpleName())); + } + /** * Provides the set of property names, which are common for entity types used in "polymorphic" association. * * @param type - * @param propertyFilter * @return */ public static final Set commonProperties(final Class type) { @@ -199,12 +235,12 @@ public static final List unionProperties(final Class commonMethodNames(final Class type) { final List commonMethods = new ArrayList<>(); @@ -218,10 +254,9 @@ public static final List commonMethodNames(final Class commonMethods(final Class type) { final Set commonProperties = commonProperties(type); @@ -233,7 +268,7 @@ public static final List commonMethods(final Class ent * *

* Additionally, in case where the target entity is of type {@link AbstractUnionEntity} and its setter executes successfully then a union rule is enforced by invoking - * {@link AbstractUnionEntity#ensureUnion(String, AbstractEntity)}. + * {@link AbstractUnionEntity#ensureUnion(String)}. * * @param entity * @param propertyName @@ -367,13 +366,13 @@ private void revalidateDependentProperty(final MetaProperty metaProperty, fin * Determines correct newValue and oldValue. {@link Pair} is used to return a pair of values where the key represents newValue and the value represents oldValue. * * @param entity - * @param metaProperty + * @param propertyName * @param newValue * @param mutator * @return * @throws Exception */ - private Pair determineNewAndOldValues(final AbstractEntity entity, final String propertyName, final Object newValue, final Method mutator) throws Exception { + private Pair determineNewAndOldValues(final AbstractEntity entity, final String propertyName, final Object newValue, final Method mutator) { // setter? if (Mutator.SETTER == Mutator.getValueByMethod(mutator)) { // this covers both simple and collectional properties return new Pair<>(newValue, entity.get(propertyName)); @@ -386,4 +385,4 @@ private Pair determineNewAndOldValues(final AbstractEntity en return new Pair<>(newValue, null); } -} \ No newline at end of file +} diff --git a/platform-pojo-bl/src/test/java/ua/com/fielden/platform/entity/AbstractEntityTest.java b/platform-pojo-bl/src/test/java/ua/com/fielden/platform/entity/AbstractEntityTest.java index 33d803dbb1..d069513e20 100644 --- a/platform-pojo-bl/src/test/java/ua/com/fielden/platform/entity/AbstractEntityTest.java +++ b/platform-pojo-bl/src/test/java/ua/com/fielden/platform/entity/AbstractEntityTest.java @@ -1,37 +1,11 @@ package ua.com.fielden.platform.entity; -import static java.lang.String.format; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static ua.com.fielden.platform.entity.exceptions.EntityDefinitionException.INVALID_USE_FOR_PRECITION_AND_SCALE_MSG; -import static ua.com.fielden.platform.entity.exceptions.EntityDefinitionException.INVALID_USE_OF_NUMERIC_PARAMS_MSG; -import static ua.com.fielden.platform.entity.exceptions.EntityDefinitionException.INVALID_USE_OF_PARAM_LENGTH_MSG; -import static ua.com.fielden.platform.entity.exceptions.EntityDefinitionException.INVALID_VALUES_FOR_PRECITION_AND_SCALE_MSG; -import static ua.com.fielden.platform.types.try_wrapper.TryWrapper.Try; - -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Set; - +import com.google.inject.Injector; import org.apache.commons.lang3.exception.ExceptionUtils; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; - -import com.google.inject.Injector; - -import ua.com.fielden.platform.associations.one2many.incorrect.MasterEntity1; -import ua.com.fielden.platform.associations.one2many.incorrect.MasterEntity2; -import ua.com.fielden.platform.associations.one2many.incorrect.MasterEntity3; -import ua.com.fielden.platform.associations.one2many.incorrect.MasterEntity4; -import ua.com.fielden.platform.associations.one2many.incorrect.MasterEntity6; +import ua.com.fielden.platform.associations.one2many.incorrect.*; import ua.com.fielden.platform.entity.exceptions.EntityDefinitionException; import ua.com.fielden.platform.entity.exceptions.EntityException; import ua.com.fielden.platform.entity.factory.EntityFactory; @@ -45,24 +19,21 @@ import ua.com.fielden.platform.ioc.ApplicationInjectorFactory; import ua.com.fielden.platform.reflection.Finder; import ua.com.fielden.platform.reflection.TitlesDescsGetter; -import ua.com.fielden.platform.reflection.test_entities.EntityWithInvalidIntegerProp; -import ua.com.fielden.platform.reflection.test_entities.EntityWithInvalidMoneyPropWithLength; -import ua.com.fielden.platform.reflection.test_entities.EntityWithInvalidMoneyPropWithNegativePrecisionAndPositiveScale; -import ua.com.fielden.platform.reflection.test_entities.EntityWithInvalidMoneyPropWithPositivePrecisionAndNegativeScale; -import ua.com.fielden.platform.reflection.test_entities.EntityWithInvalidMoneyPropWithPrecision; -import ua.com.fielden.platform.reflection.test_entities.EntityWithInvalidMoneyPropWithScale; -import ua.com.fielden.platform.reflection.test_entities.EntityWithInvalidStringPropWithPrecision; -import ua.com.fielden.platform.reflection.test_entities.EntityWithInvalidStringPropWithScale; -import ua.com.fielden.platform.reflection.test_entities.EntityWithInvalidStringPropWithTrailingZeros; -import ua.com.fielden.platform.reflection.test_entities.SecondLevelEntity; -import ua.com.fielden.platform.reflection.test_entities.SimplePartEntity; -import ua.com.fielden.platform.reflection.test_entities.UnionEntityForReflector; +import ua.com.fielden.platform.reflection.test_entities.*; import ua.com.fielden.platform.test.CommonTestEntityModuleWithPropertyFactory; import ua.com.fielden.platform.test.EntityModuleWithPropertyFactory; import ua.com.fielden.platform.types.Money; import ua.com.fielden.platform.types.either.Either; import ua.com.fielden.platform.types.either.Left; +import java.lang.annotation.Annotation; +import java.util.*; + +import static java.lang.String.format; +import static org.junit.Assert.*; +import static ua.com.fielden.platform.entity.exceptions.EntityDefinitionException.*; +import static ua.com.fielden.platform.types.try_wrapper.TryWrapper.Try; + /** * Unit test for : *