diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceEnricher.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceEnricher.java index 1d88cb7e..a0d926c0 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceEnricher.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceEnricher.java @@ -23,6 +23,9 @@ package com.kingsrook.qqq.backend.core.instances; import java.io.Serializable; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -33,8 +36,10 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader; import com.kingsrook.qqq.backend.core.actions.metadata.JoinGraph; import com.kingsrook.qqq.backend.core.actions.permissions.BulkTableActionProcessPermissionChecker; +import com.kingsrook.qqq.backend.core.actions.values.QCustomPossibleValueProvider; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.logging.QLogger; import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData; @@ -89,6 +94,7 @@ import com.kingsrook.qqq.backend.core.scheduler.QScheduleManager; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import com.kingsrook.qqq.backend.core.utils.ListingHash; import com.kingsrook.qqq.backend.core.utils.StringUtils; +import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair; /******************************************************************************* @@ -1347,6 +1353,60 @@ public class QInstanceEnricher } } + if(possibleValueSource.getIdType() == null) + { + QTableMetaData table = qInstance.getTable(possibleValueSource.getTableName()); + if(table != null) + { + String primaryKeyField = table.getPrimaryKeyField(); + QFieldMetaData primaryKeyFieldMetaData = table.getFields().get(primaryKeyField); + if(primaryKeyFieldMetaData != null) + { + possibleValueSource.setIdType(primaryKeyFieldMetaData.getType()); + } + } + } + } + else if(QPossibleValueSourceType.ENUM.equals(possibleValueSource.getType())) + { + if(possibleValueSource.getIdType() == null) + { + if(CollectionUtils.nullSafeHasContents(possibleValueSource.getEnumValues())) + { + Object id = possibleValueSource.getEnumValues().get(0).getId(); + try + { + possibleValueSource.setIdType(QFieldType.fromClass(id.getClass())); + } + catch(Exception e) + { + LOG.warn("Error enriching possible value source with idType based on first enum value", e, logPair("possibleValueSource", possibleValueSource.getName()), logPair("id", id)); + } + } + } + } + else if(QPossibleValueSourceType.CUSTOM.equals(possibleValueSource.getType())) + { + if(possibleValueSource.getIdType() == null) + { + try + { + QCustomPossibleValueProvider customPossibleValueProvider = QCodeLoader.getCustomPossibleValueProvider(possibleValueSource); + + Method getPossibleValueMethod = customPossibleValueProvider.getClass().getDeclaredMethod("getPossibleValue", Serializable.class); + Type returnType = getPossibleValueMethod.getGenericReturnType(); + Type idType = ((ParameterizedType) returnType).getActualTypeArguments()[0]; + + if(idType instanceof Class c) + { + possibleValueSource.setIdType(QFieldType.fromClass(c)); + } + } + catch(Exception e) + { + LOG.warn("Error enriching possible value source with idType based on first custom value", e, logPair("possibleValueSource", possibleValueSource.getName())); + } + } } } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java index 58618c3e..a1edd5a9 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidator.java @@ -2075,6 +2075,8 @@ public class QInstanceValidator default -> errors.add("Unexpected possibleValueSource type: " + possibleValueSource.getType()); } + assertCondition(possibleValueSource.getIdType() != null, "possibleValueSource " + name + " is missing its idType."); + runPlugins(QPossibleValueSource.class, possibleValueSource, qInstance); } } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/possiblevalues/QPossibleValueSource.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/possiblevalues/QPossibleValueSource.java index e8fc860b..00b121b4 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/possiblevalues/QPossibleValueSource.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/possiblevalues/QPossibleValueSource.java @@ -28,6 +28,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterOrderBy; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.TopLevelMetaDataInterface; import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference; +import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType; /******************************************************************************* @@ -42,6 +43,8 @@ public class QPossibleValueSource implements TopLevelMetaDataInterface private String label; private QPossibleValueSourceType type; + private QFieldType idType; + private String valueFormat = PVSValueFormatAndFields.LABEL_ONLY.getFormat(); private List valueFields = PVSValueFormatAndFields.LABEL_ONLY.getFields(); private String valueFormatIfNotFound = null; @@ -662,4 +665,35 @@ public class QPossibleValueSource implements TopLevelMetaDataInterface return (this); } + + /******************************************************************************* + ** Getter for idType + *******************************************************************************/ + public QFieldType getIdType() + { + return (this.idType); + } + + + + /******************************************************************************* + ** Setter for idType + *******************************************************************************/ + public void setIdType(QFieldType idType) + { + this.idType = idType; + } + + + + /******************************************************************************* + ** Fluent setter for idType + *******************************************************************************/ + public QPossibleValueSource withIdType(QFieldType idType) + { + this.idType = idType; + return (this); + } + + }