diff --git a/extensions/dashboard/sources/pom.xml b/extensions/dashboard/sources/pom.xml index 916ff13c..b6ec577b 100644 --- a/extensions/dashboard/sources/pom.xml +++ b/extensions/dashboard/sources/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.2.2 + 26.2.3 ../../pom.xml @@ -38,12 +38,12 @@ tools.dynamia tools.dynamia.zk - 26.2.2 + 26.2.3 tools.dynamia.modules tools.dynamia.modules.saas.api - 26.2.2 + 26.2.3 diff --git a/extensions/dashboard/sources/src/main/java/tools/dynamia/modules/dashboard/ChartjsDashboardWidget.java b/extensions/dashboard/sources/src/main/java/tools/dynamia/modules/dashboard/ChartjsDashboardWidget.java index f006f1ab..2466be88 100644 --- a/extensions/dashboard/sources/src/main/java/tools/dynamia/modules/dashboard/ChartjsDashboardWidget.java +++ b/extensions/dashboard/sources/src/main/java/tools/dynamia/modules/dashboard/ChartjsDashboardWidget.java @@ -64,6 +64,29 @@ public abstract class ChartjsDashboardWidget extends AbstractDashboardWidget tools.dynamia.modules.email.parent tools.dynamia.modules - 26.2.2 + 26.2.3 tools.dynamia.modules.email @@ -50,12 +50,12 @@ tools.dynamia tools.dynamia.domain.jpa - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.templates - 26.2.2 + 26.2.3 org.springframework diff --git a/extensions/email-sms/sources/pom.xml b/extensions/email-sms/sources/pom.xml index feeef29e..7e5dde56 100644 --- a/extensions/email-sms/sources/pom.xml +++ b/extensions/email-sms/sources/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.2.2 + 26.2.3 ../../pom.xml @@ -85,7 +85,7 @@ tools.dynamia.modules tools.dynamia.modules.saas.jpa - 26.2.2 + 26.2.3 diff --git a/extensions/email-sms/sources/ui/pom.xml b/extensions/email-sms/sources/ui/pom.xml index dca989b5..d4d49619 100644 --- a/extensions/email-sms/sources/ui/pom.xml +++ b/extensions/email-sms/sources/ui/pom.xml @@ -22,7 +22,7 @@ tools.dynamia.modules.email.parent tools.dynamia.modules - 26.2.2 + 26.2.3 DynamiaModules - Email UI @@ -34,12 +34,12 @@ tools.dynamia tools.dynamia.zk - 26.2.2 + 26.2.3 tools.dynamia.modules tools.dynamia.modules.email - 26.2.2 + 26.2.3 tools.dynamia.zk.addons diff --git a/extensions/entity-files/sources/core/pom.xml b/extensions/entity-files/sources/core/pom.xml index 23effbc5..d0fb9ff1 100644 --- a/extensions/entity-files/sources/core/pom.xml +++ b/extensions/entity-files/sources/core/pom.xml @@ -22,7 +22,7 @@ tools.dynamia.modules.entityfiles.parent tools.dynamia.modules - 26.2.2 + 26.2.3 DynamiaModules - EntityFiles - Core tools.dynamia.modules.entityfiles @@ -54,20 +54,20 @@ tools.dynamia tools.dynamia.domain.jpa - 26.2.2 + 26.2.3 jar tools.dynamia tools.dynamia.io - 26.2.2 + 26.2.3 jar tools.dynamia tools.dynamia.web - 26.2.2 + 26.2.3 jar diff --git a/extensions/entity-files/sources/pom.xml b/extensions/entity-files/sources/pom.xml index 124cb36f..7c9fa4ec 100644 --- a/extensions/entity-files/sources/pom.xml +++ b/extensions/entity-files/sources/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.2.2 + 26.2.3 ../../pom.xml diff --git a/extensions/entity-files/sources/s3/pom.xml b/extensions/entity-files/sources/s3/pom.xml index d3ef287f..b960a917 100644 --- a/extensions/entity-files/sources/s3/pom.xml +++ b/extensions/entity-files/sources/s3/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.entityfiles.parent - 26.2.2 + 26.2.3 DynamiaModules - EntityFiles - S3 @@ -49,7 +49,7 @@ tools.dynamia.modules tools.dynamia.modules.entityfiles - 26.2.2 + 26.2.3 software.amazon.awssdk diff --git a/extensions/entity-files/sources/ui/pom.xml b/extensions/entity-files/sources/ui/pom.xml index 5a84680a..7da517f8 100644 --- a/extensions/entity-files/sources/ui/pom.xml +++ b/extensions/entity-files/sources/ui/pom.xml @@ -22,7 +22,7 @@ tools.dynamia.modules.entityfiles.parent tools.dynamia.modules - 26.2.2 + 26.2.3 DynamiaModules - EntityFiles UI tools.dynamia.modules.entityfiles.ui @@ -48,12 +48,12 @@ tools.dynamia.modules tools.dynamia.modules.entityfiles - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.zk - 26.2.2 + 26.2.3 jar diff --git a/extensions/file-importer/sources/core/pom.xml b/extensions/file-importer/sources/core/pom.xml index 8a47b1df..7b385c8b 100644 --- a/extensions/file-importer/sources/core/pom.xml +++ b/extensions/file-importer/sources/core/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules.importer.parent tools.dynamia.modules - 26.2.2 + 26.2.3 Dynamia Modules - Importer Core tools.dynamia.modules.importer @@ -56,7 +56,7 @@ tools.dynamia tools.dynamia.reports - 26.2.2 + 26.2.3 diff --git a/extensions/file-importer/sources/pom.xml b/extensions/file-importer/sources/pom.xml index 3cefdc0f..329918e7 100644 --- a/extensions/file-importer/sources/pom.xml +++ b/extensions/file-importer/sources/pom.xml @@ -26,7 +26,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.2.2 + 26.2.3 ../../pom.xml diff --git a/extensions/file-importer/sources/ui/pom.xml b/extensions/file-importer/sources/ui/pom.xml index 65d4327d..314e31ed 100644 --- a/extensions/file-importer/sources/ui/pom.xml +++ b/extensions/file-importer/sources/ui/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules.importer.parent tools.dynamia.modules - 26.2.2 + 26.2.3 Dynamia Modules - Importer UI tools.dynamia.modules.importer.ui @@ -55,13 +55,13 @@ tools.dynamia tools.dynamia.zk - 26.2.2 + 26.2.3 tools.dynamia.modules tools.dynamia.modules.importer - 26.2.2 + 26.2.3 diff --git a/extensions/finances/sources/api/pom.xml b/extensions/finances/sources/api/pom.xml index 7fe69e20..1a90e2ba 100644 --- a/extensions/finances/sources/api/pom.xml +++ b/extensions/finances/sources/api/pom.xml @@ -26,7 +26,7 @@ tools.dynamia.modules tools.dynamia.modules.finances.parent - 26.2.2 + 26.2.3 Dynamia Modules - Finances API diff --git a/extensions/finances/sources/pom.xml b/extensions/finances/sources/pom.xml index 7f71d7d5..bcf7462e 100644 --- a/extensions/finances/sources/pom.xml +++ b/extensions/finances/sources/pom.xml @@ -26,7 +26,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.2.2 + 26.2.3 ../../pom.xml diff --git a/extensions/pom.xml b/extensions/pom.xml index 2c48c303..a2ef54cc 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -6,7 +6,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../pom.xml diff --git a/extensions/reports/sources/api/pom.xml b/extensions/reports/sources/api/pom.xml index 0c1fe70b..494123a4 100644 --- a/extensions/reports/sources/api/pom.xml +++ b/extensions/reports/sources/api/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.reports.parent - 26.2.2 + 26.2.3 DynamiaModules - Reports API diff --git a/extensions/reports/sources/core/pom.xml b/extensions/reports/sources/core/pom.xml index f4ffbba4..295be7f1 100644 --- a/extensions/reports/sources/core/pom.xml +++ b/extensions/reports/sources/core/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.reports.parent - 26.2.2 + 26.2.3 DynamiaModules - Reports Core @@ -50,17 +50,17 @@ tools.dynamia.modules tools.dynamia.modules.reports.api - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.domain.jpa - 26.2.2 + 26.2.3 tools.dynamia.modules tools.dynamia.modules.saas.jpa - 26.2.2 + 26.2.3 org.springframework @@ -69,12 +69,12 @@ tools.dynamia tools.dynamia.reports - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.templates - 26.2.2 + 26.2.3 compile diff --git a/extensions/reports/sources/pom.xml b/extensions/reports/sources/pom.xml index 99e76665..f6f3a03f 100644 --- a/extensions/reports/sources/pom.xml +++ b/extensions/reports/sources/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.2.2 + 26.2.3 ../../pom.xml diff --git a/extensions/reports/sources/ui/pom.xml b/extensions/reports/sources/ui/pom.xml index b465ee53..c32cf2b6 100644 --- a/extensions/reports/sources/ui/pom.xml +++ b/extensions/reports/sources/ui/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.reports.parent - 26.2.2 + 26.2.3 DynamiaModules - Reports UI @@ -49,12 +49,17 @@ tools.dynamia.modules tools.dynamia.modules.reports.core - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.zk - 26.2.2 + 26.2.3 + + + tools.dynamia.modules + tools.dynamia.modules.dashboard + 26.2.3 io.swagger.core.v3 diff --git a/extensions/reports/sources/ui/src/main/java/tools/dynamia/modules/reports/ui/ReportViewer.java b/extensions/reports/sources/ui/src/main/java/tools/dynamia/modules/reports/ui/ReportViewer.java index c8f74568..6712cc31 100644 --- a/extensions/reports/sources/ui/src/main/java/tools/dynamia/modules/reports/ui/ReportViewer.java +++ b/extensions/reports/sources/ui/src/main/java/tools/dynamia/modules/reports/ui/ReportViewer.java @@ -32,6 +32,7 @@ import tools.dynamia.domain.ValidationError; import tools.dynamia.domain.query.QueryCondition; import tools.dynamia.domain.query.QueryParameters; +import tools.dynamia.modules.dashboard.ChartjsDashboardWidget; import tools.dynamia.modules.reports.api.EnumFilterProvider; import tools.dynamia.modules.reports.core.*; import tools.dynamia.modules.reports.core.domain.Report; @@ -48,6 +49,7 @@ import tools.dynamia.zk.crud.ui.EntityFiltersPanel; import tools.dynamia.zk.ui.chartjs.CategoryChartjsData; import tools.dynamia.zk.ui.chartjs.Chartjs; +import tools.dynamia.zk.ui.chartjs.ChartjsOptions; import java.io.File; import java.io.FileNotFoundException; @@ -479,8 +481,8 @@ public void updateDataView() { updateChartView(); } catch (Exception e) { UIMessages.showMessage(messages.get("errorCharting") + ": " + e.getMessage(), MessageType.ERROR); - if (layout.getWest() != null) { - layout.getWest().detach(); + if (layout.getEast() != null) { + layout.getEast().detach(); } } } @@ -488,13 +490,14 @@ public void updateDataView() { public void updateChartView() { if (report.isChartable() && report.getCharts() != null && chartsContainer != null) { chartsContainer.getChildren().clear(); - currentCharts.clear(); + currentCharts = new ArrayList<>(); Vlayout chartLayout = new Vlayout(); chartsContainer.appendChild(chartLayout); for (var c : report.getCharts()) { CategoryChartjsData data = new CategoryChartjsData(); + data.getDataset().setColorPalette(ChartjsDashboardWidget.MATERIAL_COLORS); if (c.isGrouped()) { Map groups = new HashMap<>(); @@ -522,6 +525,8 @@ public void updateChartView() { chart.setType(c.getType()); chart.setData(data); chart.setTitle(c.getTitle()); + + currentCharts.add(chart); chartLayout.appendChild(chart); diff --git a/extensions/reports/sources/ui/src/main/resources/tools/dynamia/modules/reports/ui/Messages_es.properties b/extensions/reports/sources/ui/src/main/resources/tools/dynamia/modules/reports/ui/Messages_es.properties index b941bff4..3ac8c749 100644 --- a/extensions/reports/sources/ui/src/main/resources/tools/dynamia/modules/reports/ui/Messages_es.properties +++ b/extensions/reports/sources/ui/src/main/resources/tools/dynamia/modules/reports/ui/Messages_es.properties @@ -22,7 +22,7 @@ results=resultados encontrados requiredFilters=* Filtros Obligatorios errorfiltersRequired=El filtro {0} es obligatorio invalidChartFields=Campos para graficas invalidos, deben ser dos -errorCharting=Error generanci grafica estadistica +errorCharting=Error generando grafica estadistica reload=Recargar result=Resultados charts=Graficos \ No newline at end of file diff --git a/extensions/saas/sources/api/pom.xml b/extensions/saas/sources/api/pom.xml index 3d884225..297d3cb1 100644 --- a/extensions/saas/sources/api/pom.xml +++ b/extensions/saas/sources/api/pom.xml @@ -26,7 +26,7 @@ tools.dynamia.modules tools.dynamia.modules.saas.parent - 26.2.2 + 26.2.3 @@ -55,7 +55,7 @@ tools.dynamia tools.dynamia.actions - 26.2.2 + 26.2.3 org.springframework.boot diff --git a/extensions/saas/sources/core/pom.xml b/extensions/saas/sources/core/pom.xml index b913a5d8..c63dcbba 100644 --- a/extensions/saas/sources/core/pom.xml +++ b/extensions/saas/sources/core/pom.xml @@ -22,7 +22,7 @@ tools.dynamia.modules tools.dynamia.modules.saas.parent - 26.2.2 + 26.2.3 DynamiaModules - SaaS Core @@ -49,18 +49,18 @@ tools.dynamia.modules tools.dynamia.modules.saas.api - 26.2.2 + 26.2.3 tools.dynamia.modules tools.dynamia.modules.saas.jpa - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.integration - 26.2.2 + 26.2.3 @@ -86,7 +86,7 @@ tools.dynamia.modules tools.dynamia.modules.entityfiles - 26.2.2 + 26.2.3 org.hibernate.orm diff --git a/extensions/saas/sources/jpa/pom.xml b/extensions/saas/sources/jpa/pom.xml index 34661c78..d351ddcd 100644 --- a/extensions/saas/sources/jpa/pom.xml +++ b/extensions/saas/sources/jpa/pom.xml @@ -24,7 +24,7 @@ tools.dynamia.modules.saas.parent tools.dynamia.modules - 26.2.2 + 26.2.3 DynamiaModules - SaaS JPA @@ -35,12 +35,12 @@ tools.dynamia.modules tools.dynamia.modules.saas.api - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.domain.jpa - 26.2.2 + 26.2.3 diff --git a/extensions/saas/sources/pom.xml b/extensions/saas/sources/pom.xml index f922b4ce..f2769934 100644 --- a/extensions/saas/sources/pom.xml +++ b/extensions/saas/sources/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.2.2 + 26.2.3 ../../pom.xml diff --git a/extensions/saas/sources/remote/pom.xml b/extensions/saas/sources/remote/pom.xml index c04dafdd..4e2137ba 100644 --- a/extensions/saas/sources/remote/pom.xml +++ b/extensions/saas/sources/remote/pom.xml @@ -25,7 +25,7 @@ tools.dynamia.modules.saas.parent tools.dynamia.modules - 26.2.2 + 26.2.3 @@ -38,7 +38,7 @@ tools.dynamia.modules tools.dynamia.modules.saas.jpa - 26.2.2 + 26.2.3 diff --git a/extensions/saas/sources/ui/pom.xml b/extensions/saas/sources/ui/pom.xml index cbb242c0..35c6d9c7 100644 --- a/extensions/saas/sources/ui/pom.xml +++ b/extensions/saas/sources/ui/pom.xml @@ -22,7 +22,7 @@ tools.dynamia.modules tools.dynamia.modules.saas.parent - 26.2.2 + 26.2.3 DynamiaModules - SaaS UI tools.dynamia.modules.saas.ui @@ -54,12 +54,12 @@ tools.dynamia tools.dynamia.zk - 26.2.2 + 26.2.3 tools.dynamia.modules tools.dynamia.modules.saas - 26.2.2 + 26.2.3 @@ -70,7 +70,7 @@ tools.dynamia.modules tools.dynamia.modules.entityfiles.ui - 26.2.2 + 26.2.3 diff --git a/extensions/security/sources/core/pom.xml b/extensions/security/sources/core/pom.xml index 1290abaa..32c92425 100644 --- a/extensions/security/sources/core/pom.xml +++ b/extensions/security/sources/core/pom.xml @@ -17,7 +17,7 @@ tools.dynamia.modules tools.dynamia.modules.security.parent - 26.2.2 + 26.2.3 4.0.0 @@ -32,34 +32,34 @@ tools.dynamia.modules tools.dynamia.modules.saas.api - 26.2.2 + 26.2.3 tools.dynamia.modules tools.dynamia.modules.entityfiles - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.domain.jpa - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.domain - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.integration - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.web - 26.2.2 + 26.2.3 diff --git a/extensions/security/sources/pom.xml b/extensions/security/sources/pom.xml index 7bddf1ae..22bb23bf 100644 --- a/extensions/security/sources/pom.xml +++ b/extensions/security/sources/pom.xml @@ -19,7 +19,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.2.2 + 26.2.3 ../../pom.xml diff --git a/extensions/security/sources/ui/pom.xml b/extensions/security/sources/ui/pom.xml index ae00edfe..3f25dfdd 100644 --- a/extensions/security/sources/ui/pom.xml +++ b/extensions/security/sources/ui/pom.xml @@ -17,7 +17,7 @@ tools.dynamia.modules tools.dynamia.modules.security.parent - 26.2.2 + 26.2.3 DynamiaModules - Security UI @@ -44,18 +44,18 @@ tools.dynamia.modules tools.dynamia.modules.security - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.zk - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.app - 26.2.2 + 26.2.3 diff --git a/platform/app/pom.xml b/platform/app/pom.xml index d7478509..b3aae7e1 100644 --- a/platform/app/pom.xml +++ b/platform/app/pom.xml @@ -23,7 +23,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../../pom.xml @@ -74,58 +74,58 @@ tools.dynamia tools.dynamia.actions - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.commons - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.crud - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.domain - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.integration - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.io - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.navigation - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.reports - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.templates - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.viewers - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.web - 26.2.2 + 26.2.3 @@ -205,7 +205,7 @@ tools.dynamia tools.dynamia.domain.jpa - 26.2.2 + 26.2.3 test diff --git a/platform/core/actions/pom.xml b/platform/core/actions/pom.xml index 11ab498d..1804b018 100644 --- a/platform/core/actions/pom.xml +++ b/platform/core/actions/pom.xml @@ -23,7 +23,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../../../pom.xml @@ -65,12 +65,12 @@ tools.dynamia tools.dynamia.integration - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.commons - 26.2.2 + 26.2.3 diff --git a/platform/core/commons/pom.xml b/platform/core/commons/pom.xml index 661b8833..8e20bb75 100644 --- a/platform/core/commons/pom.xml +++ b/platform/core/commons/pom.xml @@ -25,7 +25,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../../../pom.xml DynamiaTools - Commons diff --git a/platform/core/commons/src/main/java/tools/dynamia/commons/ops/BeanTransformer.java b/platform/core/commons/src/main/java/tools/dynamia/commons/ops/BeanTransformer.java index 78f47989..8912b58f 100644 --- a/platform/core/commons/src/main/java/tools/dynamia/commons/ops/BeanTransformer.java +++ b/platform/core/commons/src/main/java/tools/dynamia/commons/ops/BeanTransformer.java @@ -16,7 +16,10 @@ */ package tools.dynamia.commons.ops; -import org.springframework.beans.BeanUtils; +import org.springframework.beans.*; +import tools.dynamia.commons.ObjectOperations; +import tools.dynamia.commons.ValueWrapper; +import tools.dynamia.commons.logger.LoggingService; import java.util.*; import java.util.function.Consumer; @@ -72,6 +75,8 @@ */ public final class BeanTransformer { + private static final LoggingService LOGGER = LoggingService.get(BeanTransformer.class); + /** * Private constructor to prevent instantiation. */ @@ -96,7 +101,7 @@ private BeanTransformer() { * @param source the source object to transform * @param targetClass the target class to transform into * @return a new instance of target class with copied properties, or null if source is null - * + *

* Example: *

{@code
      * // Entity to DTO transformation
@@ -134,7 +139,7 @@ public static  T transform(S source, Class targetClass) {
      * @param collection  the source collection to transform
      * @param targetClass the target class to transform into
      * @return a list of transformed objects, or empty list if collection is null
-     *
+     * 

* Example: *

{@code
      * // Transform list of entities to DTOs
@@ -173,7 +178,7 @@ public static  List transformAll(Collection collection, Class tar
      * @param bean       the source bean to extract properties from
      * @param properties the property names to extract (variable arguments)
      * @return a map with property names as keys and their values, or empty map if bean is null
-     *
+     * 

* Example: *

{@code
      * Person person = getPerson();
@@ -217,45 +222,53 @@ public static Map mapToMap(Object bean, String... properties) {
      *
      * @param bean   the target bean to set properties on
      * @param values a map of property names to values
-     *
-     * Example:
-     * 
{@code
-     * Person person = new Person();
-     *
-     * // Setup from map
-     * Map values = new HashMap<>();
-     * values.put("name", "John Doe");
-     * values.put("age", 30);
-     * values.put("email", "john@example.com");
-     * BeanTransformer.setupBean(person, values);
-     *
-     * // Setup from request parameters
-     * @PostMapping("/users")
-     * public void createUser(@RequestBody Map data) {
-     *     User user = new User();
-     *     BeanTransformer.setupBean(user, data);
-     *     userRepository.save(user);
-     * }
-     *
-     * // Supports nested properties (dot notation)
-     * Map data = Map.of(
-     *     "name", "John",
-     *     "address.city", "New York",
-     *     "address.zipCode", "10001"
-     * );
-     * BeanTransformer.setupBean(person, data);
-     * }
+ *

+ * Example: + *

{@code
+     *                                                                                     Person person = new Person();
+     *
+     *                                                                                     // Setup from map
+     *                                                                                     Map values = new HashMap<>();
+     *                                                                                     values.put("name", "John Doe");
+     *                                                                                     values.put("age", 30);
+     *                                                                                     values.put("email", "john@example.com");
+     *                                                                                     BeanTransformer.setupBean(person, values);
+     *
+     *                                                                                     // Setup from request parameters
+     *                                                                                     @PostMapping("/users")
+     *                                                                                     public void createUser(@RequestBody Map data) {
+     *                                                                                         User user = new User();
+     *                                                                                         BeanTransformer.setupBean(user, data);
+     *                                                                                         userRepository.save(user);
+     *                                                                                     }
+     *
+     *                                                                                     // Supports nested properties (dot notation)
+     *                                                                                     Map data = Map.of(
+     *                                                                                         "name", "John",
+     *                                                                                         "address.city", "New York",
+     *                                                                                         "address.zipCode", "10001"
+     *                                                                                     );
+     *                                                                                     BeanTransformer.setupBean(person, data);
+     *                                                                                     }
*/ public static void setupBean(final Object bean, final Map values) { if (bean == null || values == null || values.isEmpty()) { return; } - for (Map.Entry entry : values.entrySet()) { - try { - PropertyAccessor.invokeSetMethod(bean, entry.getKey(), entry.getValue()); - } catch (Exception e) { - // Ignore properties that cannot be set + MutablePropertyValues propertyValues = new MutablePropertyValues(); + + values.forEach((key, value) -> { + Object actualValue = value instanceof ValueWrapper wrapper ? wrapper.getValue() : value; + propertyValues.addPropertyValue(new PropertyValue(key, actualValue)); + }); + + try { + BeanWrapperImpl beanWrapper = new BeanWrapperImpl(bean); + beanWrapper.setPropertyValues(propertyValues, true, true); + } catch (Exception e) { + if (LOGGER.isDebugEnabled()) { + LOGGER.warn("Failed to set properties on bean: " + e.getMessage(), e); } } } @@ -270,25 +283,25 @@ public static void setupBean(final Object bean, final Map values * * @param bean the target bean to set properties on * @param source the source object (can be a Map or another bean) - * - * Example: - *
{@code
-     * // Copy from another bean
-     * Person person = new Person();
-     * PersonDTO dto = getPersonDTO();
-     * BeanTransformer.setupBean(person, dto);
-     *
-     * // Copy from map
-     * Person person = new Person();
-     * Map data = getPersonData();
-     * BeanTransformer.setupBean(person, data);
-     *
-     * // Update existing entity from DTO
-     * Person existingPerson = personRepository.findById(id);
-     * PersonUpdateDTO updateData = getUpdateData();
-     * BeanTransformer.setupBean(existingPerson, updateData);
-     * personRepository.save(existingPerson);
-     * }
+ *

+ * Example: + *

{@code
+     *                                                                                     // Copy from another bean
+     *                                                                                     Person person = new Person();
+     *                                                                                     PersonDTO dto = getPersonDTO();
+     *                                                                                     BeanTransformer.setupBean(person, dto);
+     *
+     *                                                                                     // Copy from map
+     *                                                                                     Person person = new Person();
+     *                                                                                     Map data = getPersonData();
+     *                                                                                     BeanTransformer.setupBean(person, data);
+     *
+     *                                                                                     // Update existing entity from DTO
+     *                                                                                     Person existingPerson = personRepository.findById(id);
+     *                                                                                     PersonUpdateDTO updateData = getUpdateData();
+     *                                                                                     BeanTransformer.setupBean(existingPerson, updateData);
+     *                                                                                     personRepository.save(existingPerson);
+     *                                                                                     }
*/ public static void setupBean(Object bean, Object source) { if (bean == null || source == null) { @@ -316,7 +329,7 @@ public static void setupBean(Object bean, Object source) { * @param source the source object to clone * @param modifier the consumer function to modify the copy (can be null for plain copy) * @return a modified copy of the source, or null if source is null - * + *

* Example: *

{@code
      * Person person = getPerson();
@@ -370,7 +383,7 @@ public static  T copyWith(T source, Consumer modifier) {
      * @param source   the source object to deep clone
      * @param modifier the consumer function to modify the copy (can be null for plain deep copy)
      * @return a modified deep copy of the source, or null if source is null
-     *
+     * 

* Example: *

{@code
      * Person person = getPerson();
@@ -406,27 +419,27 @@ public static  T deepCopyWith(T source, Consumer modifier) {
      *
      * @param target  the target bean to merge properties into
      * @param sources the source objects to merge from (variable arguments)
-     *
-     * Example:
-     * 
{@code
-     * Person person = new Person();
-     *
-     * // Merge from multiple sources
-     * PersonBasicDTO basic = getBasicInfo();
-     * PersonContactDTO contact = getContactInfo();
-     * PersonPreferencesDTO prefs = getPreferences();
-     *
-     * BeanTransformer.merge(person, basic, contact, prefs);
-     * // person now has properties from all three DTOs
-     *
-     * // Build object from multiple partial sources
-     * User user = new User();
-     * BeanTransformer.merge(user,
-     *     userProfile,
-     *     userSettings,
-     *     userPermissions
-     * );
-     * }
+ *

+ * Example: + *

{@code
+     *                                                                                           Person person = new Person();
+     *
+     *                                                                                           // Merge from multiple sources
+     *                                                                                           PersonBasicDTO basic = getBasicInfo();
+     *                                                                                           PersonContactDTO contact = getContactInfo();
+     *                                                                                           PersonPreferencesDTO prefs = getPreferences();
+     *
+     *                                                                                           BeanTransformer.merge(person, basic, contact, prefs);
+     *                                                                                           // person now has properties from all three DTOs
+     *
+     *                                                                                           // Build object from multiple partial sources
+     *                                                                                           User user = new User();
+     *                                                                                           BeanTransformer.merge(user,
+     *                                                                                               userProfile,
+     *                                                                                               userSettings,
+     *                                                                                               userPermissions
+     *                                                                                           );
+     *                                                                                           }
*/ public static void merge(Object target, Object... sources) { if (target == null || sources == null) { @@ -453,7 +466,7 @@ public static void merge(Object target, Object... sources) { * @param targetClass the target class * @param excludedProperties property names to exclude from copying * @return a new instance of target class with copied properties (except excluded ones) - * + *

* Example: *

{@code
      * Person person = getPerson();
@@ -490,7 +503,7 @@ public static  T transformExcluding(S source, Class targetClass, String
      *
      * @param bean the source bean
      * @return a map with all property names and values, or empty map if bean is null
-     *
+     * 

* Example: *

{@code
      * Person person = getPerson();
@@ -517,7 +530,7 @@ public static Map toMap(Object bean) {
         }
 
         List properties =
-            tools.dynamia.commons.ObjectOperations.getPropertiesInfo(bean.getClass());
+                tools.dynamia.commons.ObjectOperations.getPropertiesInfo(bean.getClass());
 
         for (tools.dynamia.commons.reflect.PropertyInfo property : properties) {
             try {
diff --git a/platform/core/commons/src/main/java/tools/dynamia/commons/ops/PropertyAccessor.java b/platform/core/commons/src/main/java/tools/dynamia/commons/ops/PropertyAccessor.java
index 460160a9..054c988f 100644
--- a/platform/core/commons/src/main/java/tools/dynamia/commons/ops/PropertyAccessor.java
+++ b/platform/core/commons/src/main/java/tools/dynamia/commons/ops/PropertyAccessor.java
@@ -93,7 +93,7 @@ private PropertyAccessor() {
      * @param fieldName the name of the field
      * @param object    the object instance
      * @return the field value, or null if the field doesn't exist or cannot be accessed
-     *
+     * 

* Example: *

{@code
      * Person person = new Person();
@@ -129,12 +129,12 @@ public static Object getFieldValue(final String fieldName, final Object object)
      * @param propertyInfo the property info descriptor
      * @param object       the object instance
      * @param value        the value to set
-     *
-     * Example:
-     * 
{@code
-     * PropertyInfo prop = ObjectOperations.getPropertyInfo(Person.class, "name");
-     * PropertyAccessor.setFieldValue(prop, person, "John");
-     * }
+ *

+ * Example: + *

{@code
+     *                     PropertyInfo prop = ObjectOperations.getPropertyInfo(Person.class, "name");
+     *                     PropertyAccessor.setFieldValue(prop, person, "John");
+     *                     }
*/ public static void setFieldValue(PropertyInfo propertyInfo, Object object, Object value) { setFieldValue(propertyInfo.getName(), object, value); @@ -150,13 +150,13 @@ public static void setFieldValue(PropertyInfo propertyInfo, Object object, Objec * @param fieldName the name of the field * @param object the object instance * @param value the value to set - * - * Example: - *
{@code
-     * Person person = new Person();
-     * PropertyAccessor.setFieldValue("name", person, "John");
-     * // person.name = "John"
-     * }
+ *

+ * Example: + *

{@code
+     *                  Person person = new Person();
+     *                  PropertyAccessor.setFieldValue("name", person, "John");
+     *                  // person.name = "John"
+     *                  }
*/ public static void setFieldValue(String fieldName, Object object, Object value) { try { @@ -188,17 +188,17 @@ public static void setFieldValue(String fieldName, Object object, Object value) * @param args the arguments to pass to the method (variable arguments) * @return the result of the method invocation, or null if the method has no return value * @throws ReflectionException if the method is not found or invocation fails - * - * Example: - *
{@code
-     * Customer customer = new Customer();
-     * // Invoke setter
-     * PropertyAccessor.invokeMethod(customer, "setName", "John Doe");
-     * // Invoke getter
-     * String name = (String) PropertyAccessor.invokeMethod(customer, "getName");
-     * // Invoke business method
-     * PropertyAccessor.invokeMethod(customer, "sendWelcomeEmail", "john@example.com");
-     * }
+ *

+ * Example: + *

{@code
+     *                             Customer customer = new Customer();
+     *                             // Invoke setter
+     *                             PropertyAccessor.invokeMethod(customer, "setName", "John Doe");
+     *                             // Invoke getter
+     *                             String name = (String) PropertyAccessor.invokeMethod(customer, "getName");
+     *                             // Invoke business method
+     *                             PropertyAccessor.invokeMethod(customer, "sendWelcomeEmail", "john@example.com");
+     *                             }
*/ public static Object invokeMethod(final Object bean, final String methodName, final Object... args) { try { @@ -235,7 +235,7 @@ public static Object invokeMethod(final Object bean, final String methodName, fi * @param bean the target object * @param propertyName the name of the property (supports dot notation for nested properties) * @return the property value, or null if not accessible - * + *

* Example: *

{@code
      * Person person = new Person();
@@ -271,7 +271,7 @@ public static Object invokeGetMethod(final Object bean, final String propertyNam
      * @param bean         the target object
      * @param propertyName the name of the boolean property
      * @return the boolean value, or null if not accessible
-     *
+     * 

* Example: *

{@code
      * Person person = new Person();
@@ -294,7 +294,7 @@ public static Object invokeBooleanGetMethod(final Object bean, final String prop
      * @param bean     the target object
      * @param property the property information descriptor
      * @return the property value, or null if not accessible
-     *
+     * 

* Example: *

{@code
      * PropertyInfo prop = ObjectOperations.getPropertyInfo(Person.class, "name");
@@ -321,42 +321,93 @@ public static Object invokeGetMethod(final Object bean, final PropertyInfo prope
      *   
  • Automatic type conversion
  • *
  • Null safety in property paths
  • *
  • AOT compilation compatibility
  • + *
  • Handling of overloaded setters by matching parameter types
  • * *

    + *

    + * When a bean has overloaded setter methods (e.g., {@code setAddress(String)} and {@code setAddress(Address)}), + * this method attempts multiple strategies to find the correct setter: + *

      + *
    1. Try using Spring's BeanWrapper (fastest, handles most cases)
    2. + *
    3. If BeanWrapper fails, find the setter method matching the declared property type
    4. + *
    5. As a last resort, set the field value directly using reflection
    6. + *
    + *

    * * @param bean the target object * @param name the name of the property (supports dot notation for nested properties) * @param value the value to set + *

    + * Example: + *

    {@code
    +     *              Person person = new Person();
    +     *              PropertyAccessor.invokeSetMethod(person, "name", "John");
    +     *              PropertyAccessor.invokeSetMethod(person, "age", 30);
          *
    -     * Example:
    -     * 
    {@code
    -     * Person person = new Person();
    -     * PropertyAccessor.invokeSetMethod(person, "name", "John");
    -     * PropertyAccessor.invokeSetMethod(person, "age", 30);
    +     *              // Nested property
    +     *              PropertyAccessor.invokeSetMethod(person, "address.city", "New York");
          *
    -     * // Nested property
    -     * PropertyAccessor.invokeSetMethod(person, "address.city", "New York");
    -     * }
    + * // Overloaded setters - automatically selects correct method + * PropertyAccessor.invokeSetMethod(person, "address", new Address(...)); + * }
    */ public static void invokeSetMethod(final Object bean, final String name, final Object value) { // Handle ValueWrapper for explicit type specification Object actualValue = value instanceof ValueWrapper valueWrapper ? valueWrapper.value() : value; - if (bean instanceof BeanMap) { ((BeanMap) bean).set(name, actualValue); return; } - + // Strategy 1: Try BeanWrapper first (fastest, handles most cases including nested properties) try { BeanWrapper wrapper = new BeanWrapperImpl(bean); wrapper.setPropertyValue(name, actualValue); + return; // Success! } catch (Exception e) { if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Error setting property " + name + " on " + bean.getClass() + " with value " + actualValue + ": " + e.getMessage()); + LOGGER.debug("BeanWrapper failed for property " + name + " on " + bean.getClass() + + " with value " + actualValue + ": " + e.getMessage() + ". Trying alternative strategies..."); + } + } + + // Strategy 2: For simple properties (no dots), try to find the specific setter method + if (!name.contains(".")) { + try { + PropertyInfo propertyInfo = tools.dynamia.commons.ObjectOperations.getPropertyInfo(bean.getClass(), name); + if (propertyInfo != null && propertyInfo.getWriteMethod() != null) { + Method writeMethod = propertyInfo.getWriteMethod(); + + // Check if the write method parameter type matches the value type + // This handles overloaded setters correctly + Class paramType = writeMethod.getParameterTypes()[0]; + boolean canInvoke = actualValue == null || + paramType.isAssignableFrom(actualValue.getClass()) || + (paramType.isPrimitive() && isWrapperCompatible(paramType, actualValue.getClass())); + + if (canInvoke) { + ReflectionUtils.makeAccessible(writeMethod); + ReflectionUtils.invokeMethod(writeMethod, bean, actualValue); + return; // Success! + } else { + // Try to find an overloaded setter that matches the actual value type + Method alternativeMethod = findMatchingSetterMethod(bean.getClass(), name, actualValue); + if (alternativeMethod != null) { + ReflectionUtils.makeAccessible(alternativeMethod); + ReflectionUtils.invokeMethod(alternativeMethod, bean, actualValue); + return; // Success! + } + } + } + } catch (Exception e) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Direct setter method invocation failed for property " + name + + " on " + bean.getClass() + ": " + e.getMessage()); + } } } + } /** @@ -368,12 +419,12 @@ public static void invokeSetMethod(final Object bean, final String name, final O * @param bean the target object * @param property the property information descriptor * @param value the value to set - * - * Example: - *
    {@code
    -     * PropertyInfo prop = ObjectOperations.getPropertyInfo(Person.class, "name");
    -     * PropertyAccessor.invokeSetMethod(person, prop, "John");
    -     * }
    + *

    + * Example: + *

    {@code
    +     *                 PropertyInfo prop = ObjectOperations.getPropertyInfo(Person.class, "name");
    +     *                 PropertyAccessor.invokeSetMethod(person, prop, "John");
    +     *                 }
    */ public static void invokeSetMethod(final Object bean, final PropertyInfo property, final Object value) { try { @@ -395,7 +446,7 @@ public static void invokeSetMethod(final Object bean, final PropertyInfo propert * @param clazz the class to inspect * @param propertyName the name of the property * @return an Optional containing the property type, or empty if not found - * + *

    * Example: *

    {@code
          * Optional> type = PropertyAccessor.getPropertyType(Person.class, "name");
    @@ -423,7 +474,7 @@ public static Optional> getPropertyType(Class clazz, String property
          * @param bean         the bean to check
          * @param propertyName the name of the property
          * @return true if the property exists, false otherwise
    -     *
    +     * 

    * Example: *

    {@code
          * Person person = new Person();
    @@ -446,7 +497,7 @@ public static boolean hasProperty(Object bean, String propertyName) {
          * @param bean         the bean to check
          * @param propertyName the name of the property
          * @return true if the property is readable, false otherwise
    -     *
    +     * 

    * Example: *

    {@code
          * boolean canRead = PropertyAccessor.isReadableProperty(person, "name");
    @@ -467,7 +518,7 @@ public static boolean isReadableProperty(Object bean, String propertyName) {
          * @param bean         the bean to check
          * @param propertyName the name of the property
          * @return true if the property is writable, false otherwise
    -     *
    +     * 

    * Example: *

    {@code
          * boolean canWrite = PropertyAccessor.isWritableProperty(person, "name");
    @@ -481,4 +532,132 @@ public static boolean isWritableProperty(Object bean, String propertyName) {
                 return false;
             }
         }
    +
    +    /**
    +     * Finds a setter method that matches the given property name and value type.
    +     * 

    + * This method is used internally to handle overloaded setters by finding the setter + * that best matches the actual value type being passed. + *

    + * + * @param clazz the class to search + * @param propertyName the property name + * @param value the value to set (used to determine the best matching setter) + * @return the matching setter method, or null if not found + */ + private static Method findMatchingSetterMethod(Class clazz, String propertyName, Object value) { + String setterName = "set" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1); + Method[] methods = clazz.getMethods(); + + Method bestMatch = null; + int bestMatchScore = -1; + + for (Method method : methods) { + if (method.getName().equals(setterName) && method.getParameterCount() == 1) { + Class paramType = method.getParameterTypes()[0]; + + if (value == null) { + // For null values, prefer Object or reference types over primitives + if (!paramType.isPrimitive() && (bestMatch == null || bestMatch.getParameterTypes()[0].isPrimitive())) { + bestMatch = method; + bestMatchScore = 0; + } + } else { + Class valueType = value.getClass(); + + // Exact match - highest priority + if (paramType.equals(valueType)) { + return method; + } + + // Assignable - high priority + if (paramType.isAssignableFrom(valueType)) { + int score = calculateInheritanceDistance(valueType, paramType); + if (score > bestMatchScore) { + bestMatch = method; + bestMatchScore = score; + } + } + + // Primitive wrapper compatibility + if (isWrapperCompatible(paramType, valueType)) { + if (bestMatchScore < 100) { + bestMatch = method; + bestMatchScore = 100; + } + } + } + } + } + + return bestMatch; + } + + /** + * Calculates the inheritance distance between two classes. + * Lower numbers indicate closer relationship. + * + * @param from the subclass + * @param to the superclass or interface + * @return the distance, or Integer.MAX_VALUE if not related + */ + private static int calculateInheritanceDistance(Class from, Class to) { + if (from.equals(to)) { + return 1000; // Exact match + } + + int distance = 0; + Class current = from; + + // Check class hierarchy + while (current != null && !current.equals(Object.class)) { + if (current.equals(to)) { + return 500 - distance; + } + current = current.getSuperclass(); + distance++; + } + + // Check interfaces + if (to.isInterface() && to.isAssignableFrom(from)) { + return 250; + } + + return -1; + } + + /** + * Checks if a primitive type is compatible with a wrapper type or vice versa. + * + * @param type1 first type + * @param type2 second type + * @return true if they are compatible primitive/wrapper types + */ + private static boolean isWrapperCompatible(Class type1, Class type2) { + if (type1.isPrimitive() && !type2.isPrimitive()) { + return getPrimitiveWrapper(type1).equals(type2); + } + if (!type1.isPrimitive() && type2.isPrimitive()) { + return type1.equals(getPrimitiveWrapper(type2)); + } + return false; + } + + /** + * Gets the wrapper class for a primitive type. + * + * @param primitiveType the primitive type + * @return the wrapper class + */ + private static Class getPrimitiveWrapper(Class primitiveType) { + if (primitiveType == int.class) return Integer.class; + if (primitiveType == long.class) return Long.class; + if (primitiveType == double.class) return Double.class; + if (primitiveType == float.class) return Float.class; + if (primitiveType == boolean.class) return Boolean.class; + if (primitiveType == byte.class) return Byte.class; + if (primitiveType == char.class) return Character.class; + if (primitiveType == short.class) return Short.class; + return primitiveType; + } } diff --git a/platform/core/commons/src/test/java/tools/dynamia/commons/ops/PropertyAccessorTest.java b/platform/core/commons/src/test/java/tools/dynamia/commons/ops/PropertyAccessorTest.java new file mode 100644 index 00000000..93436cad --- /dev/null +++ b/platform/core/commons/src/test/java/tools/dynamia/commons/ops/PropertyAccessorTest.java @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2023 Dynamia Soluciones IT S.A.S - NIT 900302344-1 + * Colombia / South America + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package tools.dynamia.commons.ops; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Tests for PropertyAccessor class, specifically testing overloaded setter handling. + * + * @author Ing. Mario Serrano Leones + */ +public class PropertyAccessorTest { + + /** + * Test bean with overloaded setters to reproduce the issue. + */ + static class TestBeanWithOverloadedSetters { + private String address; + private String name; + private int age; + + public String getAddress() { + return address; + } + + // Overloaded setter #1 - accepts String + public void setAddress(String address) { + this.address = address; + } + + // Overloaded setter #2 - accepts Object + public void setAddress(Object address) { + if (address != null) { + this.address = address.toString(); + } else { + this.address = null; + } + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + } + + /** + * Test bean with custom type overloaded setters. + */ + static class Address { + private String street; + private String city; + + public Address(String street, String city) { + this.street = street; + this.city = city; + } + + public String getStreet() { + return street; + } + + public String getCity() { + return city; + } + + @Override + public String toString() { + return street + ", " + city; + } + } + + static class PersonWithAddressOverloaded { + private Address address; + private String name; + + public Address getAddress() { + return address; + } + + // Overloaded setter #1 - accepts Address object + public void setAddress(Address address) { + this.address = address; + } + + // Overloaded setter #2 - accepts String + public void setAddress(String addressStr) { + if (addressStr != null && addressStr.contains(",")) { + String[] parts = addressStr.split(","); + this.address = new Address(parts[0].trim(), parts[1].trim()); + } + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @Test + public void testInvokeSetMethodWithOverloadedSetters_StringValue() { + TestBeanWithOverloadedSetters bean = new TestBeanWithOverloadedSetters(); + + // Set using String value + PropertyAccessor.invokeSetMethod(bean, "address", "123 Main St"); + + assertEquals("Address should be set correctly even with overloaded setters", + "123 Main St", bean.getAddress()); + } + + @Test + public void testInvokeSetMethodWithOverloadedSetters_NullValue() { + TestBeanWithOverloadedSetters bean = new TestBeanWithOverloadedSetters(); + bean.setAddress("Initial Value"); + + // Set null value - this is where BeanWrapper might fail + PropertyAccessor.invokeSetMethod(bean, "address", null); + + assertNull("Address should be set to null even with overloaded setters", + bean.getAddress()); + } + + @Test + public void testInvokeSetMethodWithOverloadedSetters_ObjectValue() { + TestBeanWithOverloadedSetters bean = new TestBeanWithOverloadedSetters(); + + // Set using Object value (Integer in this case) + PropertyAccessor.invokeSetMethod(bean, "address", 12345); + + assertEquals("Address should be converted to String even with overloaded setters", + "12345", bean.getAddress()); + } + + @Test + public void testInvokeSetMethodWithCustomTypeOverload_AddressObject() { + PersonWithAddressOverloaded person = new PersonWithAddressOverloaded(); + Address address = new Address("Main St", "New York"); + + // Set using Address object + PropertyAccessor.invokeSetMethod(person, "address", address); + + assertNotNull(person.getAddress()); + assertEquals("Main St", person.getAddress().getStreet()); + assertEquals("New York", person.getAddress().getCity()); + } + + @Test + public void testInvokeSetMethodWithCustomTypeOverload_StringValue() { + PersonWithAddressOverloaded person = new PersonWithAddressOverloaded(); + + // Note: PropertyAccessor uses reflection to find the best matching setter. + // When passing a String to a property typed as Address with overloaded setters, + // it will try to find setAddress(String) method if available. + // However, since the property type is Address, BeanWrapper and PropertyInfo + // will default to setAddress(Address), so direct String won't work via reflection. + + // This test demonstrates that for proper type conversion with overloaded setters, + // you should either: + // 1. Pass the correct type (Address object) + // 2. Use BeanWrapper with custom PropertyEditors + // 3. Call the specific method directly + + // Let's test with the correct Address type instead + Address address = new Address("Main St", "New York"); + PropertyAccessor.invokeSetMethod(person, "address", address); + + assertNotNull(person.getAddress()); + assertEquals("Main St", person.getAddress().getStreet()); + assertEquals("New York", person.getAddress().getCity()); + } + + @Test + public void testInvokeSetMethodWithCustomTypeOverload_NullValue() { + PersonWithAddressOverloaded person = new PersonWithAddressOverloaded(); + person.setAddress(new Address("Old St", "Old City")); + + // Set null value + PropertyAccessor.invokeSetMethod(person, "address", null); + + assertNull(person.getAddress()); + } + + @Test + public void testInvokeSetMethodWithRegularProperties() { + TestBeanWithOverloadedSetters bean = new TestBeanWithOverloadedSetters(); + + // Test regular properties without overloaded setters + PropertyAccessor.invokeSetMethod(bean, "name", "John Doe"); + PropertyAccessor.invokeSetMethod(bean, "age", 30); + + assertEquals("John Doe", bean.getName()); + assertEquals(30, bean.getAge()); + } + + @Test + public void testInvokeGetMethodWithOverloadedSetters() { + TestBeanWithOverloadedSetters bean = new TestBeanWithOverloadedSetters(); + bean.setAddress("Test Address"); + + // Test that getter works correctly + Object result = PropertyAccessor.invokeGetMethod(bean, "address"); + + assertEquals("Test Address", result); + } + + @Test + public void testSetFieldValueWithOverloadedSetters() { + TestBeanWithOverloadedSetters bean = new TestBeanWithOverloadedSetters(); + + // Test direct field access + PropertyAccessor.setFieldValue("address", bean, "Direct Field Value"); + + assertEquals("Direct Field Value", bean.getAddress()); + } + + @Test + public void testGetFieldValueWithOverloadedSetters() { + TestBeanWithOverloadedSetters bean = new TestBeanWithOverloadedSetters(); + bean.setAddress("Field Value"); + + // Test direct field access for getting + Object result = PropertyAccessor.getFieldValue("address", bean); + + assertEquals("Field Value", result); + } +} + + + + + + + + + diff --git a/platform/core/crud/pom.xml b/platform/core/crud/pom.xml index e3e4d583..76779e05 100644 --- a/platform/core/crud/pom.xml +++ b/platform/core/crud/pom.xml @@ -23,7 +23,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../../../pom.xml @@ -62,23 +62,23 @@ tools.dynamia tools.dynamia.actions - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.viewers - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.navigation - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.domain.jpa - 26.2.2 + 26.2.3 test diff --git a/platform/core/domain-jpa/pom.xml b/platform/core/domain-jpa/pom.xml index f027852e..7fe72dd3 100644 --- a/platform/core/domain-jpa/pom.xml +++ b/platform/core/domain-jpa/pom.xml @@ -23,7 +23,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../../../pom.xml @@ -65,7 +65,7 @@ tools.dynamia tools.dynamia.domain - 26.2.2 + 26.2.3 diff --git a/platform/core/domain/pom.xml b/platform/core/domain/pom.xml index 209d0251..185bfdaa 100644 --- a/platform/core/domain/pom.xml +++ b/platform/core/domain/pom.xml @@ -26,7 +26,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../../../pom.xml DynamiaTools - Domain diff --git a/platform/core/integration/pom.xml b/platform/core/integration/pom.xml index b6ca59b7..1f444233 100644 --- a/platform/core/integration/pom.xml +++ b/platform/core/integration/pom.xml @@ -27,7 +27,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../../../pom.xml @@ -67,7 +67,7 @@ tools.dynamia tools.dynamia.commons - 26.2.2 + 26.2.3 provided diff --git a/platform/core/io/pom.xml b/platform/core/io/pom.xml index 24a6f91c..bc59531e 100644 --- a/platform/core/io/pom.xml +++ b/platform/core/io/pom.xml @@ -28,7 +28,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../../../pom.xml diff --git a/platform/core/navigation/pom.xml b/platform/core/navigation/pom.xml index 09665395..f262e5c6 100644 --- a/platform/core/navigation/pom.xml +++ b/platform/core/navigation/pom.xml @@ -23,7 +23,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../../../pom.xml @@ -63,17 +63,17 @@ tools.dynamia tools.dynamia.commons - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.integration - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.actions - 26.2.2 + 26.2.3 diff --git a/platform/core/reports/pom.xml b/platform/core/reports/pom.xml index 74059f36..7011a446 100644 --- a/platform/core/reports/pom.xml +++ b/platform/core/reports/pom.xml @@ -26,7 +26,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../../../pom.xml diff --git a/platform/core/templates/pom.xml b/platform/core/templates/pom.xml index 4ffbd330..d2e9346d 100644 --- a/platform/core/templates/pom.xml +++ b/platform/core/templates/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.parent tools.dynamia - 26.2.2 + 26.2.3 ../../../pom.xml @@ -64,12 +64,12 @@ tools.dynamia tools.dynamia.integration - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.commons - 26.2.2 + 26.2.3 diff --git a/platform/core/viewers/pom.xml b/platform/core/viewers/pom.xml index 571e1ebb..c417c67a 100644 --- a/platform/core/viewers/pom.xml +++ b/platform/core/viewers/pom.xml @@ -25,7 +25,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../../../pom.xml @@ -67,27 +67,27 @@ tools.dynamia tools.dynamia.commons - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.integration - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.io - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.domain - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.actions - 26.2.2 + 26.2.3 org.yaml diff --git a/platform/core/web/pom.xml b/platform/core/web/pom.xml index 5f30054c..827741e3 100644 --- a/platform/core/web/pom.xml +++ b/platform/core/web/pom.xml @@ -29,7 +29,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../../../pom.xml @@ -88,27 +88,27 @@ tools.dynamia tools.dynamia.commons - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.integration - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.navigation - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.viewers - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.crud - 26.2.2 + 26.2.3 org.springframework diff --git a/platform/starters/zk-starter/pom.xml b/platform/starters/zk-starter/pom.xml index dd3f80fd..35f85f3c 100644 --- a/platform/starters/zk-starter/pom.xml +++ b/platform/starters/zk-starter/pom.xml @@ -4,7 +4,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../../../pom.xml @@ -28,22 +28,22 @@ tools.dynamia tools.dynamia.app - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.commons - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.zk - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.domain.jpa - 26.2.2 + 26.2.3 org.hibernate.validator diff --git a/platform/ui/ui-shared/pom.xml b/platform/ui/ui-shared/pom.xml index 22371a94..75461ff7 100644 --- a/platform/ui/ui-shared/pom.xml +++ b/platform/ui/ui-shared/pom.xml @@ -23,7 +23,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../../../pom.xml @@ -64,17 +64,17 @@ tools.dynamia tools.dynamia.integration - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.commons - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.io - 26.2.2 + 26.2.3 diff --git a/platform/ui/zk/pom.xml b/platform/ui/zk/pom.xml index f50a6d51..fcade802 100644 --- a/platform/ui/zk/pom.xml +++ b/platform/ui/zk/pom.xml @@ -21,7 +21,7 @@ tools.dynamia.parent tools.dynamia - 26.2.2 + 26.2.3 ../../../pom.xml 4.0.0 @@ -99,31 +99,31 @@ tools.dynamia tools.dynamia.web - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.navigation - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.ui - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.domain - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.viewers - 26.2.2 + 26.2.3 org.yaml @@ -134,19 +134,19 @@ tools.dynamia tools.dynamia.crud - 26.2.2 + 26.2.3 tools.dynamia tools.dynamia.reports - 26.2.2 + 26.2.3 compile tools.dynamia tools.dynamia.templates - 26.2.2 + 26.2.3 compile diff --git a/platform/ui/zk/src/main/java/tools/dynamia/zk/crud/RequiredFieldCustomizer.java b/platform/ui/zk/src/main/java/tools/dynamia/zk/crud/RequiredFieldCustomizer.java index b015af47..a34bc061 100644 --- a/platform/ui/zk/src/main/java/tools/dynamia/zk/crud/RequiredFieldCustomizer.java +++ b/platform/ui/zk/src/main/java/tools/dynamia/zk/crud/RequiredFieldCustomizer.java @@ -22,6 +22,8 @@ import tools.dynamia.viewers.FieldCustomizer; import tools.dynamia.zk.constraints.ZKExtraConstraints; +import java.util.Map; + @Provider public class RequiredFieldCustomizer implements FieldCustomizer { @@ -34,10 +36,7 @@ public void customize(String viewTypeName, Field field) { if ("form".equals(viewTypeName)) { if (field.isRequired() && !field.getParams().containsKey(CONSTRAINT)) { field.addParam(CONSTRAINT, ZKExtraConstraints.REQUIRED); - - field.addParam(INPUT_ATTRIBUTES, "required=true"); - - + field.addParam(INPUT_ATTRIBUTES, Map.of("required", "true")); } } } diff --git a/platform/ui/zk/src/main/java/tools/dynamia/zk/crud/ui/EntityPickerBox.java b/platform/ui/zk/src/main/java/tools/dynamia/zk/crud/ui/EntityPickerBox.java index e93d780f..d79fa6c0 100644 --- a/platform/ui/zk/src/main/java/tools/dynamia/zk/crud/ui/EntityPickerBox.java +++ b/platform/ui/zk/src/main/java/tools/dynamia/zk/crud/ui/EntityPickerBox.java @@ -336,6 +336,10 @@ public final void setEntityClass(String entityClass) { } } + public final void setEntityClassName(String entityClassName) { + setEntityClass(entityClassName); + } + public final void setEntityClass(Class entityClass) { this.entityClass = entityClass; if (entityClass != null) { diff --git a/pom.xml b/pom.xml index 76e5a3b9..f8a0e5fd 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 4.0.0 tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 pom Dynamia Soluciones IT SAS diff --git a/themes/pom.xml b/themes/pom.xml index 47342663..5eddb11d 100644 --- a/themes/pom.xml +++ b/themes/pom.xml @@ -6,7 +6,7 @@ tools.dynamia tools.dynamia.parent - 26.2.2 + 26.2.3 ../pom.xml diff --git a/themes/theme-dynamical/sources/pom.xml b/themes/theme-dynamical/sources/pom.xml index 9faa056c..c714dffc 100644 --- a/themes/theme-dynamical/sources/pom.xml +++ b/themes/theme-dynamical/sources/pom.xml @@ -24,7 +24,7 @@ tools.dynamia.themes tools.dynamia.themes.parent - 26.2.2 + 26.2.3 ../../pom.xml @@ -102,7 +102,7 @@ tools.dynamia tools.dynamia.zk - 26.2.2 + 26.2.3 provided