diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/customizers/AbstractPostQueryCustomizer.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/customizers/AbstractPostQueryCustomizer.java
new file mode 100644
index 00000000..d1beaa4c
--- /dev/null
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/customizers/AbstractPostQueryCustomizer.java
@@ -0,0 +1,65 @@
+/*
+ * QQQ - Low-code Application Framework for Engineers.
+ * Copyright (C) 2021-2022. 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.actions.customizers;
+
+
+import java.util.List;
+import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
+import com.kingsrook.qqq.backend.core.model.data.QRecord;
+
+
+/*******************************************************************************
+ **
+ *******************************************************************************/
+public abstract class AbstractPostQueryCustomizer
+{
+ protected AbstractTableActionInput input;
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ public abstract List apply(List records);
+
+
+
+ /*******************************************************************************
+ ** Getter for input
+ **
+ *******************************************************************************/
+ public AbstractTableActionInput getInput()
+ {
+ return (input);
+ }
+
+
+
+ /*******************************************************************************
+ ** Setter for input
+ **
+ *******************************************************************************/
+ public void setInput(AbstractTableActionInput input)
+ {
+ this.input = input;
+ }
+}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/customizers/TableCustomizers.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/customizers/TableCustomizers.java
index 36e467df..2d2d6621 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/customizers/TableCustomizers.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/customizers/TableCustomizers.java
@@ -22,10 +22,6 @@
package com.kingsrook.qqq.backend.core.actions.customizers;
-import java.util.function.Function;
-import com.kingsrook.qqq.backend.core.model.data.QRecord;
-
-
/*******************************************************************************
** Enum definition of possible table customizers - "roles" for custom code that
** can be applied to tables.
@@ -43,13 +39,7 @@ import com.kingsrook.qqq.backend.core.model.data.QRecord;
*******************************************************************************/
public enum TableCustomizers
{
- POST_QUERY_RECORD(new TableCustomizer("postQueryRecord", Function.class, ((Object x) ->
- {
- @SuppressWarnings("unchecked")
- Function function = (Function) x;
- QRecord output = function.apply(new QRecord());
- }))),
-
+ POST_QUERY_RECORD(new TableCustomizer("postQueryRecord", AbstractPostQueryCustomizer.class)),
POST_INSERT_RECORD(new TableCustomizer("postInsertRecord", AbstractPostInsertCustomizer.class));
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/widgets/ProcessWidgetRenderer.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/widgets/ProcessWidgetRenderer.java
index f13fbbc6..bdbf8382 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/widgets/ProcessWidgetRenderer.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/dashboard/widgets/ProcessWidgetRenderer.java
@@ -55,7 +55,6 @@ public class ProcessWidgetRenderer extends AbstractWidgetRenderer
if(input.getWidgetMetaData() instanceof QWidgetMetaData widgetMetaData)
{
setupDropdowns(input, widgetMetaData, data);
- // todo - something about an error-like screen if dropdowns aren't valid?
String processName = (String) widgetMetaData.getDefaultValues().get(WIDGET_PROCESS_NAME);
QProcessMetaData processMetaData = input.getInstance().getProcess(processName);
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/GetAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/GetAction.java
index f6162271..e6b2329b 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/GetAction.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/GetAction.java
@@ -28,8 +28,8 @@ import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.function.Function;
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
+import com.kingsrook.qqq.backend.core.actions.customizers.AbstractPostQueryCustomizer;
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers;
import com.kingsrook.qqq.backend.core.actions.interfaces.GetInterface;
@@ -64,7 +64,7 @@ import org.apache.commons.lang.NotImplementedException;
*******************************************************************************/
public class GetAction
{
- private Optional> postGetRecordCustomizer;
+ private Optional postGetRecordCustomizer;
private GetInput getInput;
private QValueFormatter qValueFormatter;
@@ -80,7 +80,7 @@ public class GetAction
ActionHelper.validateSession(getInput);
QTableMetaData table = getInput.getTable();
- postGetRecordCustomizer = QCodeLoader.getTableCustomizerFunction(table, TableCustomizers.POST_QUERY_RECORD.getRole());
+ postGetRecordCustomizer = QCodeLoader.getTableCustomizer(AbstractPostQueryCustomizer.class, table, TableCustomizers.POST_QUERY_RECORD.getRole());
this.getInput = getInput;
QBackendModuleDispatcher qBackendModuleDispatcher = new QBackendModuleDispatcher();
@@ -325,7 +325,7 @@ public class GetAction
QRecord returnRecord = record;
if(this.postGetRecordCustomizer.isPresent())
{
- returnRecord = postGetRecordCustomizer.get().apply(record);
+ returnRecord = postGetRecordCustomizer.get().apply(List.of(record)).get(0);
}
if(getInput.getShouldTranslatePossibleValues())
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/QueryAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/QueryAction.java
index 845a49b3..e757a4ae 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/QueryAction.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/QueryAction.java
@@ -24,8 +24,8 @@ package com.kingsrook.qqq.backend.core.actions.tables;
import java.util.List;
import java.util.Optional;
-import java.util.function.Function;
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
+import com.kingsrook.qqq.backend.core.actions.customizers.AbstractPostQueryCustomizer;
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers;
import com.kingsrook.qqq.backend.core.actions.values.QPossibleValueTranslator;
@@ -44,10 +44,9 @@ import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface;
*******************************************************************************/
public class QueryAction
{
- private Optional> postQueryRecordCustomizer;
+ private Optional postQueryRecordCustomizer;
private QueryInput queryInput;
- private QValueFormatter qValueFormatter;
private QPossibleValueTranslator qPossibleValueTranslator;
@@ -59,7 +58,7 @@ public class QueryAction
{
ActionHelper.validateSession(queryInput);
- postQueryRecordCustomizer = QCodeLoader.getTableCustomizerFunction(queryInput.getTable(), TableCustomizers.POST_QUERY_RECORD.getRole());
+ postQueryRecordCustomizer = QCodeLoader.getTableCustomizer(AbstractPostQueryCustomizer.class, queryInput.getTable(), TableCustomizers.POST_QUERY_RECORD.getRole());
this.queryInput = queryInput;
if(queryInput.getRecordPipe() != null)
@@ -92,7 +91,7 @@ public class QueryAction
{
if(this.postQueryRecordCustomizer.isPresent())
{
- records.replaceAll(t -> postQueryRecordCustomizer.get().apply(t));
+ records = postQueryRecordCustomizer.get().apply(records);
}
if(queryInput.getShouldTranslatePossibleValues())
@@ -106,11 +105,7 @@ public class QueryAction
if(queryInput.getShouldGenerateDisplayValues())
{
- if(qValueFormatter == null)
- {
- qValueFormatter = new QValueFormatter();
- }
- qValueFormatter.setDisplayValuesInRecords(queryInput.getTable(), records);
+ QValueFormatter.setDisplayValuesInRecords(queryInput.getTable(), records);
}
}
}
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 6d1c1834..4e2271d0 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
@@ -784,6 +784,9 @@ public class QInstanceValidator
}
else if(!Modifier.isPublic(clazz.getModifiers()))
{
+ //////////////////////////////////////////////////////////////
+ // seems like this doesn't get hit, for private classses... //
+ //////////////////////////////////////////////////////////////
errors.add(prefix + " because it is not public");
}
else
@@ -794,7 +797,7 @@ public class QInstanceValidator
boolean hasNoArgConstructor = Stream.of(clazz.getConstructors()).anyMatch(c -> c.getParameterCount() == 0);
if(!hasNoArgConstructor)
{
- errors.add(prefix + " because it does not have a parameterless constructor");
+ errors.add(prefix + " because it does not have a public parameterless constructor");
}
else
{
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/WidgetDropdownData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/WidgetDropdownData.java
index da2af156..54cdf91f 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/WidgetDropdownData.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/dashboard/WidgetDropdownData.java
@@ -23,7 +23,7 @@ package com.kingsrook.qqq.backend.core.model.metadata.dashboard;
/*******************************************************************************
- ** inner class for specifying details about dropdown fields on a parent widget
+ ** Details about dropdown fields on a widget
**
*******************************************************************************/
public class WidgetDropdownData
diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidatorTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidatorTest.java
index 11ae63ff..14e1d2c8 100644
--- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidatorTest.java
+++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/QInstanceValidatorTest.java
@@ -27,7 +27,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.function.Consumer;
-import java.util.function.Function;
+import com.kingsrook.qqq.backend.core.actions.customizers.AbstractPostQueryCustomizer;
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers;
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
import com.kingsrook.qqq.backend.core.exceptions.QException;
@@ -387,17 +387,17 @@ class QInstanceValidatorTest
assertValidationFailureReasons((qInstance) -> qInstance.getTable("person").withCustomizer(TableCustomizers.POST_QUERY_RECORD.getRole(), new QCodeReference(CustomizerWithNoVoidConstructor.class, QCodeUsage.CUSTOMIZER)),
"Instance of " + CustomizerWithNoVoidConstructor.class.getSimpleName() + " could not be created");
- assertValidationFailureReasons((qInstance) -> qInstance.getTable("person").withCustomizer(TableCustomizers.POST_QUERY_RECORD.getRole(), new QCodeReference(CustomizerThatIsNotAFunction.class, QCodeUsage.CUSTOMIZER)),
+ assertValidationFailureReasons((qInstance) -> qInstance.getTable("person").withCustomizer(TableCustomizers.POST_QUERY_RECORD.getRole(), new QCodeReference(CustomizerThatIsNotOfTheRightBaseClass.class, QCodeUsage.CUSTOMIZER)),
"CodeReference is not of the expected type");
- assertValidationFailureReasons((qInstance) -> qInstance.getTable("person").withCustomizer(TableCustomizers.POST_QUERY_RECORD.getRole(), new QCodeReference(CustomizerFunctionWithIncorrectTypeParameters.class, QCodeUsage.CUSTOMIZER)),
- "Error validating customizer type parameters");
+ assertValidationFailureReasons((qInstance) -> qInstance.getTable("person").withCustomizer(TableCustomizers.POST_QUERY_RECORD.getRole(), new QCodeReference(CustomizerWithOnlyPrivateConstructor.class, QCodeUsage.CUSTOMIZER)),
+ "it does not have a public parameterless constructor");
- assertValidationFailureReasons((qInstance) -> qInstance.getTable("person").withCustomizer(TableCustomizers.POST_QUERY_RECORD.getRole(), new QCodeReference(CustomizerFunctionWithIncorrectTypeParameter1.class, QCodeUsage.CUSTOMIZER)),
- "Error validating customizer type parameters");
-
- assertValidationFailureReasons((qInstance) -> qInstance.getTable("person").withCustomizer(TableCustomizers.POST_QUERY_RECORD.getRole(), new QCodeReference(CustomizerFunctionWithIncorrectTypeParameter2.class, QCodeUsage.CUSTOMIZER)),
- "Error validating customizer type parameters");
+ /////////////////////////////////////////////
+ // this class actually works, so, :shrug:? //
+ /////////////////////////////////////////////
+ // assertValidationFailureReasons((qInstance) -> qInstance.getTable("person").withCustomizer(TableCustomizers.POST_QUERY_RECORD.getRole(), new QCodeReference(CustomizerWithPrivateVisibility.class, QCodeUsage.CUSTOMIZER)),
+ // "it does not have a public parameterless constructor");
assertValidationSuccess((qInstance) -> qInstance.getTable("person").withCustomizer(TableCustomizers.POST_QUERY_RECORD.getRole(), new QCodeReference(CustomizerValid.class, QCodeUsage.CUSTOMIZER)));
}
@@ -417,6 +417,30 @@ class QInstanceValidatorTest
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ private static class CustomizerWithPrivateVisibility extends AbstractPostQueryCustomizer
+ {
+ public CustomizerWithPrivateVisibility()
+ {
+ System.out.println("eh?");
+ }
+
+
+
+ /*******************************************************************************
+ **
+ *******************************************************************************/
+ @Override
+ public List apply(List records)
+ {
+ return (records);
+ }
+ }
+
+
+
/*******************************************************************************
**
*******************************************************************************/
@@ -433,7 +457,7 @@ class QInstanceValidatorTest
/*******************************************************************************
**
*******************************************************************************/
- public static class CustomizerThatIsNotAFunction
+ public static class CustomizerThatIsNotOfTheRightBaseClass
{
}
@@ -442,54 +466,12 @@ class QInstanceValidatorTest
/*******************************************************************************
**
*******************************************************************************/
- public static class CustomizerFunctionWithIncorrectTypeParameters implements Function
+ public static class CustomizerValid extends AbstractPostQueryCustomizer
{
@Override
- public String apply(String s)
+ public List apply(List records)
{
- return null;
- }
- }
-
-
-
- /*******************************************************************************
- **
- *******************************************************************************/
- public static class CustomizerFunctionWithIncorrectTypeParameter1 implements Function
- {
- @Override
- public QRecord apply(String s)
- {
- return null;
- }
- }
-
-
-
- /*******************************************************************************
- **
- *******************************************************************************/
- public static class CustomizerFunctionWithIncorrectTypeParameter2 implements Function
- {
- @Override
- public String apply(QRecord s)
- {
- return "Test";
- }
- }
-
-
-
- /*******************************************************************************
- **
- *******************************************************************************/
- public static class CustomizerValid implements Function
- {
- @Override
- public QRecord apply(QRecord record)
- {
- return null;
+ return (records);
}
}
diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryBackendModuleTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryBackendModuleTest.java
index 21e00c65..d2f70281 100644
--- a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryBackendModuleTest.java
+++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/modules/backend/implementations/memory/MemoryBackendModuleTest.java
@@ -25,7 +25,7 @@ package com.kingsrook.qqq.backend.core.modules.backend.implementations.memory;
import java.time.LocalDate;
import java.time.Month;
import java.util.List;
-import java.util.function.Function;
+import com.kingsrook.qqq.backend.core.actions.customizers.AbstractPostQueryCustomizer;
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers;
import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction;
@@ -472,13 +472,15 @@ class MemoryBackendModuleTest
///////////////////////////////////////////////////////
// do a query - assert that the customizer did stuff //
///////////////////////////////////////////////////////
- ShapeTestCustomizer.executionCount = 0;
+ ShapeTestCustomizer.invocationCount = 0;
+ ShapeTestCustomizer.recordsCustomizedCount = 0;
QueryInput queryInput = new QueryInput(qInstance);
queryInput.setSession(session);
queryInput.setTableName(table.getName());
QueryOutput queryOutput = new QueryAction().execute(queryInput);
assertEquals(3, queryOutput.getRecords().size());
- assertEquals(3, ShapeTestCustomizer.executionCount);
+ assertEquals(1, ShapeTestCustomizer.invocationCount);
+ assertEquals(3, ShapeTestCustomizer.recordsCustomizedCount);
assertTrue(queryOutput.getRecords().stream().anyMatch(r -> r.getValueInteger("id").equals(1) && r.getValueInteger("tenTimesId").equals(10)));
assertTrue(queryOutput.getRecords().stream().anyMatch(r -> r.getValueInteger("id").equals(2) && r.getValueInteger("tenTimesId").equals(20)));
assertTrue(queryOutput.getRecords().stream().anyMatch(r -> r.getValueInteger("id").equals(3) && r.getValueInteger("tenTimesId").equals(30)));
@@ -489,18 +491,26 @@ class MemoryBackendModuleTest
/*******************************************************************************
**
*******************************************************************************/
- public static class ShapeTestCustomizer implements Function
+ public static class ShapeTestCustomizer extends AbstractPostQueryCustomizer
{
- static int executionCount = 0;
+ static int invocationCount = 0;
+ static int recordsCustomizedCount = 0;
+ /*******************************************************************************
+ **
+ *******************************************************************************/
@Override
- public QRecord apply(QRecord record)
+ public List apply(List records)
{
- executionCount++;
- record.setValue("tenTimesId", record.getValueInteger("id") * 10);
- return (record);
+ invocationCount++;
+ for(QRecord record : records)
+ {
+ recordsCustomizedCount++;
+ record.setValue("tenTimesId", record.getValueInteger("id") * 10);
+ }
+ return (records);
}
}
}
\ No newline at end of file