From 2031e05117a0f659d229c3092f5dca5c9aba7117 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Fri, 31 Jan 2025 14:29:51 -0600 Subject: [PATCH] Update QMetaDataProducingEntity to know how to produce table meta data; Add MetaDataCustomizers to work with producer helpers --- .../metadata/MetaDataProducerHelper.java | 127 +++++++++++++- ...omRecordEntityGenericMetaDataProducer.java | 26 ++- .../MetaDataCustomizerInterface.java | 56 +++++++ ...dEntityToTableGenericMetaDataProducer.java | 157 ++++++++++++++++++ .../annotations/ChildRecordListWidget.java | 3 + .../annotations/QMetaDataProducingEntity.java | 5 +- .../metadata/MetaDataProducerHelperTest.java | 12 ++ .../TestMetaDataProducingEntity.java | 56 ++++++- 8 files changed, 419 insertions(+), 23 deletions(-) create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/MetaDataCustomizerInterface.java create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/RecordEntityToTableGenericMetaDataProducer.java diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelper.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelper.java index f0a97220..e0b51958 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelper.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelper.java @@ -41,12 +41,15 @@ import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData; import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.PossibleValueEnum; import com.kingsrook.qqq.backend.core.model.metadata.producers.ChildJoinFromRecordEntityGenericMetaDataProducer; import com.kingsrook.qqq.backend.core.model.metadata.producers.ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer; +import com.kingsrook.qqq.backend.core.model.metadata.producers.MetaDataCustomizerInterface; import com.kingsrook.qqq.backend.core.model.metadata.producers.PossibleValueSourceOfEnumGenericMetaDataProducer; import com.kingsrook.qqq.backend.core.model.metadata.producers.PossibleValueSourceOfTableGenericMetaDataProducer; +import com.kingsrook.qqq.backend.core.model.metadata.producers.RecordEntityToTableGenericMetaDataProducer; import com.kingsrook.qqq.backend.core.model.metadata.producers.annotations.ChildRecordListWidget; import com.kingsrook.qqq.backend.core.model.metadata.producers.annotations.ChildTable; import com.kingsrook.qqq.backend.core.model.metadata.producers.annotations.QMetaDataProducingEntity; import com.kingsrook.qqq.backend.core.model.metadata.producers.annotations.QMetaDataProducingPossibleValueEnum; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.utils.ClassPathUtils; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils; @@ -83,6 +86,27 @@ public class MetaDataProducerHelper comparatorValuesByType.put(QAppMetaData.class, 23); } + private static MetaDataCustomizerInterface tableMetaDataCustomizer = null; + + + + /******************************************************************************* + ** Recursively find all classes in the given package, that implement MetaDataProducerInterface + ** run them, and add their output to the given qInstance - using the provided + ** tableMetaDataCustomizer to help with all RecordEntity's that + ** are configured to make tables. + ** + ** Note - they'll be sorted by the sortOrder they provide. + *******************************************************************************/ + public static void processAllMetaDataProducersInPackage(QInstance instance, String packageName, MetaDataCustomizerInterface tableMetaDataCustomizer) throws QException + { + MetaDataProducerHelper.tableMetaDataCustomizer = tableMetaDataCustomizer; + processAllMetaDataProducersInPackage(instance, packageName); + MetaDataProducerHelper.tableMetaDataCustomizer = null; + } + + + /******************************************************************************* ** Recursively find all classes in the given package, that implement MetaDataProducerInterface ** run them, and add their output to the given qInstance. @@ -117,20 +141,27 @@ public class MetaDataProducerHelper continue; } + ///////////////////////////////////////////////////////////////////// + // handle classes which are themselves MetaDataProducerInterface's // + ///////////////////////////////////////////////////////////////////// if(MetaDataProducerInterface.class.isAssignableFrom(aClass)) { CollectionUtils.addIfNotNull(producers, processMetaDataProducer(aClass)); } + ///////////////////////////////////////////////////////////////////////// + // handle classes that have the @QMetaDataProducingEntity annotation - // + // record entities that should produce meta-data // + ///////////////////////////////////////////////////////////////////////// if(aClass.isAnnotationPresent(QMetaDataProducingEntity.class)) { - QMetaDataProducingEntity qMetaDataProducingEntity = aClass.getAnnotation(QMetaDataProducingEntity.class); - if(qMetaDataProducingEntity.producePossibleValueSource()) - { - producers.addAll(processMetaDataProducingEntity(aClass)); - } + producers.addAll(processMetaDataProducingEntity(aClass)); } + ////////////////////////////////////////////////////////////////// + // handle classes with the @QMetaDataProducingPossibleValueEnum // + // enums that are PVS's // + ////////////////////////////////////////////////////////////////// if(aClass.isAnnotationPresent(QMetaDataProducingPossibleValueEnum.class)) { QMetaDataProducingPossibleValueEnum qMetaDataProducingPossibleValueEnum = aClass.getAnnotation(QMetaDataProducingPossibleValueEnum.class); @@ -220,13 +251,24 @@ public class MetaDataProducerHelper { List> rs = new ArrayList<>(); - String warningPrefix = "Found a class annotated as @" + QMetaDataProducingEntity.class.getSimpleName(); + QMetaDataProducingEntity qMetaDataProducingEntity = aClass.getAnnotation(QMetaDataProducingEntity.class); + String warningPrefix = "Found a class annotated as @" + QMetaDataProducingEntity.class.getSimpleName(); + + /////////////////////////////////////////////////////////// + // make sures class is QRecordEntity and cast it as such // + /////////////////////////////////////////////////////////// if(!QRecordEntity.class.isAssignableFrom(aClass)) { LOG.warn(warningPrefix + ", but which is not a " + QRecordEntity.class.getSimpleName() + ", so it will not be used.", logPair("class", aClass.getSimpleName())); return (rs); } + @SuppressWarnings("unchecked") // safe per the check above. + Class recordEntityClass = (Class) aClass; + + //////////////////////////////////////////////// + // get TABLE_NAME static field from the class // + //////////////////////////////////////////////// Field tableNameField = aClass.getDeclaredField("TABLE_NAME"); if(!tableNameField.getType().equals(String.class)) { @@ -235,12 +277,50 @@ public class MetaDataProducerHelper } String tableNameValue = (String) tableNameField.get(null); - rs.add(new PossibleValueSourceOfTableGenericMetaDataProducer(tableNameValue)); + + ////////////////////////////////////////// + // add table producer, if so configured // + ////////////////////////////////////////// + if(qMetaDataProducingEntity.produceTableMetaData()) + { + try + { + //////////////////////////////////////////////////////// + // todo - better to check the runtime type parameter? // + //////////////////////////////////////////////////////// + Class> genericMetaProductionCustomizer = (Class>) qMetaDataProducingEntity.tableMetaDataCustomizer(); + Class> tableMetaDataProductionCustomizer = null; + if(!genericMetaProductionCustomizer.equals(MetaDataCustomizerInterface.NoopMetaDataCustomizer.class)) + { + tableMetaDataProductionCustomizer = (Class>) genericMetaProductionCustomizer; + } + + RecordEntityToTableGenericMetaDataProducer producer = new RecordEntityToTableGenericMetaDataProducer(tableNameValue, recordEntityClass, tableMetaDataProductionCustomizer); + + if(tableMetaDataCustomizer != null) + { + producer.addRecordEntityTableMetaDataProductionCustomizer(tableMetaDataCustomizer); + } + + rs.add(producer); + } + catch(Exception e) + { + throw new QException("Error processing table meta data producer for entity class: " + recordEntityClass.getName(), e); + } + } + + //////////////////////////////////////// + // add PVS producer, if so configured // + //////////////////////////////////////// + if(qMetaDataProducingEntity.producePossibleValueSource()) + { + rs.add(new PossibleValueSourceOfTableGenericMetaDataProducer(tableNameValue)); + } ////////////////////////// // process child tables // ////////////////////////// - QMetaDataProducingEntity qMetaDataProducingEntity = aClass.getAnnotation(QMetaDataProducingEntity.class); for(ChildTable childTable : qMetaDataProducingEntity.childTables()) { Class childEntityClass = childTable.childTableEntityClass(); @@ -362,4 +442,35 @@ public class MetaDataProducerHelper String tableNameValue = (String) tableNameField.get(null); return (tableNameValue); } + + + + /******************************************************************************* + ** Getter for tableMetaDataCustomizer + *******************************************************************************/ + public MetaDataCustomizerInterface getTableMetaDataCustomizer() + { + return (MetaDataProducerHelper.tableMetaDataCustomizer); + } + + + + /******************************************************************************* + ** Setter for tableMetaDataCustomizer + *******************************************************************************/ + public void setTableMetaDataCustomizer(MetaDataCustomizerInterface tableMetaDataCustomizer) + { + MetaDataProducerHelper.tableMetaDataCustomizer = tableMetaDataCustomizer; + } + + + + /******************************************************************************* + ** Fluent setter for tableMetaDataCustomizer + *******************************************************************************/ + public void withTableMetaDataCustomizer(MetaDataCustomizerInterface tableMetaDataCustomizer) + { + MetaDataProducerHelper.tableMetaDataCustomizer = tableMetaDataCustomizer; + } + } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer.java index cb8d451f..d9d7858c 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer.java @@ -38,14 +38,14 @@ import com.kingsrook.qqq.backend.core.utils.StringUtils; ** produce a QJoinMetaData, based on a QRecordEntity and a ChildTable sub-annotation. ** ** e.g., Orders & LineItems - on the Order entity - ** + @QMetaDataProducingEntity( childTables = { @ChildTable( - childTableEntityClass = LineItem.class, - childJoin = @ChildJoin(enabled = true), - childRecordListWidget = @ChildRecordListWidget(enabled = true, label = "Order Lines")) + childTableEntityClass = LineItem.class, + childJoin = @ChildJoin(enabled = true), + childRecordListWidget = @ChildRecordListWidget(enabled = true, label = "Order Lines")) }) public class Order extends QRecordEntity - ** + ** *******************************************************************************/ public class ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer implements MetaDataProducerInterface @@ -53,6 +53,8 @@ public class ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer implem private String childTableName; // e.g., lineItem private String parentTableName; // e.g., order + private MetaDataCustomizerInterface widgetMetaDataProductionCustomizer = null; + private ChildRecordListWidget childRecordListWidget; @@ -60,11 +62,18 @@ public class ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer implem /*************************************************************************** ** ***************************************************************************/ - public ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer(String childTableName, String parentTableName, ChildRecordListWidget childRecordListWidget) + public ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer(String childTableName, String parentTableName, ChildRecordListWidget childRecordListWidget) throws Exception { this.childTableName = childTableName; this.parentTableName = parentTableName; this.childRecordListWidget = childRecordListWidget; + + Class> genericMetaProductionCustomizer = (Class>) childRecordListWidget.widgetMetaDataCustomizer(); + if(!genericMetaProductionCustomizer.equals(MetaDataCustomizerInterface.NoopMetaDataCustomizer.class)) + { + Class> widgetMetaProductionCustomizerClass = (Class>) genericMetaProductionCustomizer; + this.widgetMetaDataProductionCustomizer = widgetMetaProductionCustomizerClass.getConstructor().newInstance(); + } } @@ -94,6 +103,11 @@ public class ChildRecordListWidgetFromRecordEntityGenericMetaDataProducer implem widget.withDefaultValue("maxRows", childRecordListWidget.maxRows()); } + if(this.widgetMetaDataProductionCustomizer != null) + { + widget = this.widgetMetaDataProductionCustomizer.customizeMetaData(qInstance, widget); + } + return (widget); } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/MetaDataCustomizerInterface.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/MetaDataCustomizerInterface.java new file mode 100644 index 00000000..8fd3cf82 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/MetaDataCustomizerInterface.java @@ -0,0 +1,56 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2025. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.core.model.metadata.producers; + + +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.TopLevelMetaDataInterface; + + +/******************************************************************************* + ** + *******************************************************************************/ +public interface MetaDataCustomizerInterface +{ + /*************************************************************************** + ** + ***************************************************************************/ + T customizeMetaData(QInstance qInstance, T metaData) throws QException; + + + /*************************************************************************** + ** noop version of this interface - used as default value in annotation + ** + ***************************************************************************/ + class NoopMetaDataCustomizer implements MetaDataCustomizerInterface + { + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public T customizeMetaData(QInstance qInstance, T metaData) throws QException + { + return (metaData); + } + } +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/RecordEntityToTableGenericMetaDataProducer.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/RecordEntityToTableGenericMetaDataProducer.java new file mode 100644 index 00000000..21565148 --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/RecordEntityToTableGenericMetaDataProducer.java @@ -0,0 +1,157 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2024. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.backend.core.model.metadata.producers; + + +import java.util.ArrayList; +import java.util.List; +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.model.data.QRecordEntity; +import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducerInterface; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; +import com.kingsrook.qqq.backend.core.utils.CollectionUtils; +import com.kingsrook.qqq.backend.core.utils.StringUtils; + + +/*************************************************************************** + ** Generic meta-data-producer, which should be instantiated (e.g., by + ** MetaDataProducerHelper), to produce a QPossibleValueSource meta-data + ** based on a QRecordEntity class (which has corresponding QTableMetaData). + ** + ***************************************************************************/ +public class RecordEntityToTableGenericMetaDataProducer implements MetaDataProducerInterface +{ + private final String tableName; + private final Class entityClass; + + private final List> metaDataCustomizers = new ArrayList<>(); + + private static MetaDataCustomizerInterface defaultMetaDataCustomizer = null; + + + + /******************************************************************************* + ** Constructor + ** + *******************************************************************************/ + public RecordEntityToTableGenericMetaDataProducer(String tableName, Class entityClass, Class> metaDataProductionCustomizerClass) throws QException + { + this.tableName = tableName; + this.entityClass = entityClass; + + if(metaDataProductionCustomizerClass != null) + { + metaDataCustomizers.add(getMetaDataProductionCustomizer(metaDataProductionCustomizerClass)); + } + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public QTableMetaData produce(QInstance qInstance) throws QException + { + QTableMetaData qTableMetaData = new QTableMetaData(); + qTableMetaData.setName(tableName); + qTableMetaData.setRecordLabelFormat("%s"); + qTableMetaData.withFieldsFromEntity(entityClass); + + //////////////////////////////////////////////////////////////////// + // use the productionCustomizers to fill in more of the meta data // + //////////////////////////////////////////////////////////////////// + for(MetaDataCustomizerInterface metaDataMetaDataCustomizer : metaDataCustomizers) + { + qTableMetaData = metaDataMetaDataCustomizer.customizeMetaData(qInstance, qTableMetaData); + } + + /////////////////////////////////////////////////////////////////////////////////// + // now if there's a default customizer, call it too - for generic, common things // + // you might want on all of your tables, or defaults if not set otherwise // + /////////////////////////////////////////////////////////////////////////////////// + if(defaultMetaDataCustomizer != null) + { + qTableMetaData = defaultMetaDataCustomizer.customizeMetaData(qInstance, qTableMetaData); + } + + ///////////////////////////////////////////////////////////////////////// + // use primary key as record label field, if it hasn't been set so far // + // todo - does this belong in the enricher?? // + ///////////////////////////////////////////////////////////////////////// + if(CollectionUtils.nullSafeIsEmpty(qTableMetaData.getRecordLabelFields()) && StringUtils.hasContent(qTableMetaData.getPrimaryKeyField())) + { + qTableMetaData.setRecordLabelFields(List.of(qTableMetaData.getPrimaryKeyField())); + } + + return qTableMetaData; + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + private MetaDataCustomizerInterface getMetaDataProductionCustomizer(Class> metaDataCustomizerClass) throws QException + { + try + { + return metaDataCustomizerClass.getConstructor().newInstance(); + } + catch(Exception e) + { + throw (new QException("Error constructing table metadata production customizer class [" + metaDataCustomizerClass + "]: ", e)); + } + } + + + + /*************************************************************************** + ** + ***************************************************************************/ + public void addRecordEntityTableMetaDataProductionCustomizer(MetaDataCustomizerInterface metaDataMetaDataCustomizer) + { + metaDataCustomizers.add(metaDataMetaDataCustomizer); + } + + + + /******************************************************************************* + ** Getter for defaultMetaDataCustomizer + *******************************************************************************/ + public static MetaDataCustomizerInterface getDefaultMetaDataCustomizer() + { + return (RecordEntityToTableGenericMetaDataProducer.defaultMetaDataCustomizer); + } + + + + /******************************************************************************* + ** Setter for defaultMetaDataCustomizer + *******************************************************************************/ + public static void setDefaultMetaDataCustomizer(MetaDataCustomizerInterface defaultMetaDataCustomizer) + { + RecordEntityToTableGenericMetaDataProducer.defaultMetaDataCustomizer = defaultMetaDataCustomizer; + } + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/annotations/ChildRecordListWidget.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/annotations/ChildRecordListWidget.java index 9a5299c5..f0952335 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/annotations/ChildRecordListWidget.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/annotations/ChildRecordListWidget.java @@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.core.model.metadata.producers.annotations; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import com.kingsrook.qqq.backend.core.model.metadata.producers.MetaDataCustomizerInterface; /*************************************************************************** @@ -43,4 +44,6 @@ public @interface ChildRecordListWidget boolean canAddChildRecords() default false; String manageAssociationName() default ""; + + Class widgetMetaDataCustomizer() default MetaDataCustomizerInterface.NoopMetaDataCustomizer.class; } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/annotations/QMetaDataProducingEntity.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/annotations/QMetaDataProducingEntity.java index 4e755163..5683baa4 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/annotations/QMetaDataProducingEntity.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/producers/annotations/QMetaDataProducingEntity.java @@ -26,6 +26,7 @@ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import com.kingsrook.qqq.backend.core.model.metadata.producers.MetaDataCustomizerInterface; /******************************************************************************* @@ -41,8 +42,10 @@ import java.lang.annotation.Target; @SuppressWarnings("checkstyle:MissingJavadocMethod") public @interface QMetaDataProducingEntity { - boolean producePossibleValueSource() default true; + boolean produceTableMetaData() default false; + Class tableMetaDataCustomizer() default MetaDataCustomizerInterface.NoopMetaDataCustomizer.class; + boolean producePossibleValueSource() default false; ChildTable[] childTables() default { }; } diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelperTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelperTest.java index 61ba8d2b..ca574ac3 100644 --- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelperTest.java +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/MetaDataProducerHelperTest.java @@ -39,6 +39,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.producers.TestMetaDataProdu import com.kingsrook.qqq.backend.core.model.metadata.producers.TestMetaDataProducingPossibleValueEnum; import com.kingsrook.qqq.backend.core.model.metadata.producers.TestNoInterfacesExtendsObject; import com.kingsrook.qqq.backend.core.model.metadata.producers.TestNoValidConstructorMetaDataProducer; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -76,6 +77,17 @@ class MetaDataProducerHelperTest assertEquals(2, enumPVS.getEnumValues().size()); assertEquals(new QPossibleValue<>(1, "One"), enumPVS.getEnumValues().get(0)); + //////////////////////////////////////////// + // annotation on table -> table meta data // + //////////////////////////////////////////// + assertTrue(qInstance.getTables().containsKey(TestMetaDataProducingEntity.TABLE_NAME)); + QTableMetaData table = qInstance.getTables().get(TestMetaDataProducingEntity.TABLE_NAME); + assertEquals(TestMetaDataProducingEntity.TABLE_NAME, table.getName()); + assertEquals("id", table.getPrimaryKeyField()); + assertEquals(2, table.getFields().size()); + assertTrue(table.getField("name").getIsRequired()); + assertEquals("Customized Label", table.getLabel()); + ////////////////////////////////////////////// // annotation on PVS table -> PVS meta data // ////////////////////////////////////////////// diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestMetaDataProducingEntity.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestMetaDataProducingEntity.java index 519d7946..cb8c903a 100644 --- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestMetaDataProducingEntity.java +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/model/metadata/producers/TestMetaDataProducingEntity.java @@ -26,7 +26,6 @@ import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.model.data.QField; import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.data.QRecordEntity; -import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducerInterface; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.producers.annotations.ChildJoin; import com.kingsrook.qqq.backend.core.model.metadata.producers.annotations.ChildRecordListWidget; @@ -38,7 +37,10 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; /******************************************************************************* ** QRecord Entity for TestMetaDataProducingEntity table *******************************************************************************/ -@QMetaDataProducingEntity(producePossibleValueSource = true, +@QMetaDataProducingEntity( + produceTableMetaData = true, + tableMetaDataCustomizer = TestMetaDataProducingEntity.TableMetaDataCustomizer.class, + producePossibleValueSource = true, childTables = { @ChildTable(childTableEntityClass = TestMetaDataProducingChildEntity.class, @@ -46,24 +48,31 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; childRecordListWidget = @ChildRecordListWidget(enabled = true, label = "Test Children", maxRows = 15)) } ) -public class TestMetaDataProducingEntity extends QRecordEntity implements MetaDataProducerInterface +public class TestMetaDataProducingEntity extends QRecordEntity { public static final String TABLE_NAME = "testMetaDataProducingEntity"; @QField(isEditable = false, isPrimaryKey = true) private Integer id; + @QField(isRequired = true) + private String name; /*************************************************************************** ** ***************************************************************************/ - @Override - public QTableMetaData produce(QInstance qInstance) throws QException + public static class TableMetaDataCustomizer implements MetaDataCustomizerInterface { - return new QTableMetaData() - .withName(TABLE_NAME) - .withFieldsFromEntity(TestMetaDataProducingEntity.class); + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public QTableMetaData customizeMetaData(QInstance qInstance, QTableMetaData table) throws QException + { + table.withLabel("Customized Label"); + return table; + } } @@ -116,4 +125,35 @@ public class TestMetaDataProducingEntity extends QRecordEntity implements MetaDa return (this); } + + /******************************************************************************* + ** Getter for name + *******************************************************************************/ + public String getName() + { + return (this.name); + } + + + + /******************************************************************************* + ** Setter for name + *******************************************************************************/ + public void setName(String name) + { + this.name = name; + } + + + + /******************************************************************************* + ** Fluent setter for name + *******************************************************************************/ + public TestMetaDataProducingEntity withName(String name) + { + this.name = name; + return (this); + } + + }