From 6d749e9df6efa1e40968e5bacb1c53db7105e839 Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Thu, 30 Jan 2025 19:11:39 -0600 Subject: [PATCH] First version of loading process meta-data via loader (steps needed discriminating loader) --- .../implementations/QStepDataLoader.java | 85 +++++++++++++++ .../processes/QFrontendComponentMetaData.java | 3 +- .../metadata/processes/QProcessMetaData.java | 2 +- .../metadata/processes/QStateMachineStep.java | 21 ++++ .../metadata/processes/QStepMetaData.java | 3 +- .../loaders/QProcessMetaDataLoaderTest.java | 103 ++++++++++++++++++ 6 files changed, 214 insertions(+), 3 deletions(-) create mode 100644 qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/loaders/implementations/QStepDataLoader.java create mode 100644 qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/loaders/QProcessMetaDataLoaderTest.java diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/loaders/implementations/QStepDataLoader.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/loaders/implementations/QStepDataLoader.java new file mode 100644 index 00000000..6333389b --- /dev/null +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/instances/loaders/implementations/QStepDataLoader.java @@ -0,0 +1,85 @@ +/* + * 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.instances.loaders.implementations; + + +import java.util.Map; +import com.kingsrook.qqq.backend.core.instances.loaders.AbstractMetaDataLoader; +import com.kingsrook.qqq.backend.core.instances.loaders.LoadingContext; +import com.kingsrook.qqq.backend.core.instances.loaders.QMetaDataLoaderException; +import com.kingsrook.qqq.backend.core.logging.QLogger; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData; +import com.kingsrook.qqq.backend.core.utils.StringUtils; +import com.kingsrook.qqq.backend.core.utils.ValueUtils; + + +/******************************************************************************* + ** + *******************************************************************************/ +public class QStepDataLoader extends AbstractMetaDataLoader +{ + private static final QLogger LOG = QLogger.getLogger(QStepDataLoader.class); + + + + /*************************************************************************** + ** + ***************************************************************************/ + @Override + public QStepMetaData mapToMetaDataObject(QInstance qInstance, Map map, LoadingContext context) throws QMetaDataLoaderException + { + String stepType = ValueUtils.getValueAsString(map.get("stepType")); + + if(!StringUtils.hasContent(stepType)) + { + throw (new QMetaDataLoaderException("stepType was not specified for process step")); + } + + QStepMetaData step; + if("backend".equalsIgnoreCase(stepType)) + { + step = new QBackendStepMetaData(); + reflectivelyMap(qInstance, step, map, context); + } + else if("frontend".equalsIgnoreCase(stepType)) + { + step = new QFrontendStepMetaData(); + reflectivelyMap(qInstance, step, map, context); + } + // todo - we have custom factory methods for this, so, maybe needs all custom loader? + // else if("stateMachine".equalsIgnoreCase(stepType)) + // { + // step = new QStateMachineStep(); + // reflectivelyMap(qInstance, step, map, context); + // } + else + { + throw (new QMetaDataLoaderException("Unsupported step stepType: " + stepType)); + } + + return (step); + } + +} diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QFrontendComponentMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QFrontendComponentMetaData.java index aa5a1f6e..35b8316c 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QFrontendComponentMetaData.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QFrontendComponentMetaData.java @@ -25,12 +25,13 @@ package com.kingsrook.qqq.backend.core.model.metadata.processes; import java.io.Serializable; import java.util.HashMap; import java.util.Map; +import com.kingsrook.qqq.backend.core.model.metadata.QMetaDataObject; /******************************************************************************* ** Definition of a UI component in a frontend process steps. *******************************************************************************/ -public class QFrontendComponentMetaData +public class QFrontendComponentMetaData implements QMetaDataObject { private QComponentType type; diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QProcessMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QProcessMetaData.java index 8bb459ef..41985ae1 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QProcessMetaData.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QProcessMetaData.java @@ -325,7 +325,7 @@ public class QProcessMetaData implements QAppChildMetaData, MetaDataWithPermissi *******************************************************************************/ public void setStepList(List stepList) { - this.stepList = stepList; + withStepList(stepList); } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QStateMachineStep.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QStateMachineStep.java index dd370142..6f47893e 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QStateMachineStep.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QStateMachineStep.java @@ -185,4 +185,25 @@ public class QStateMachineStep extends QStepMetaData return (rs); } + + /******************************************************************************* + ** Setter for subSteps + *******************************************************************************/ + public void setSubSteps(List subSteps) + { + this.subSteps = subSteps; + } + + + + /******************************************************************************* + ** Fluent setter for subSteps + *******************************************************************************/ + public QStateMachineStep withSubSteps(List subSteps) + { + this.subSteps = subSteps; + return (this); + } + + } diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QStepMetaData.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QStepMetaData.java index d2d12545..52e7c624 100644 --- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QStepMetaData.java +++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QStepMetaData.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.List; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.kingsrook.qqq.backend.core.model.metadata.QMetaDataObject; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData; import com.kingsrook.qqq.backend.core.model.metadata.serialization.QStepMetaDataDeserializer; @@ -37,7 +38,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.serialization.QStepMetaData ** *******************************************************************************/ @JsonDeserialize(using = QStepMetaDataDeserializer.class) -public abstract class QStepMetaData +public abstract class QStepMetaData implements QMetaDataObject { private String name; private String label; diff --git a/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/loaders/QProcessMetaDataLoaderTest.java b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/loaders/QProcessMetaDataLoaderTest.java new file mode 100644 index 00000000..edde858d --- /dev/null +++ b/qqq-backend-core/src/test/java/com/kingsrook/qqq/backend/core/instances/loaders/QProcessMetaDataLoaderTest.java @@ -0,0 +1,103 @@ +/* + * 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.instances.loaders; + + +import java.nio.charset.StandardCharsets; +import java.util.Map; +import com.kingsrook.qqq.backend.core.BaseTest; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QComponentType; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; +import com.kingsrook.qqq.backend.core.utils.CollectionUtils; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + + +/******************************************************************************* + ** Unit test for loading a QProcessMetaData (doesn't need its own loader yet, + ** but is still a valuable high-level test target). + *******************************************************************************/ +class QProcessMetaDataLoaderTest extends BaseTest +{ + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void testYaml() throws QMetaDataLoaderException + { + ClassDetectingMetaDataLoader metaDataLoader = new ClassDetectingMetaDataLoader(); + QProcessMetaData process = (QProcessMetaData) metaDataLoader.fileToMetaDataObject(new QInstance(), IOUtils.toInputStream(""" + class: QProcessMetaData + version: 1.0 + name: myProcess + stepList: + - name: myBackendStep + stepType: backend + code: + name: com.kingsrook.test.processes.MyBackendStep + - name: myFrontendStep + stepType: frontend + components: + - type: HELP_TEXT + values: + foo: bar + - type: VIEW_FORM + viewFields: + - name: myField + type: STRING + - name: yourField + type: DATE + """, StandardCharsets.UTF_8), "myProcess.yaml"); + + CollectionUtils.nonNullList(metaDataLoader.getProblems()).forEach(System.out::println); + + assertEquals("myProcess", process.getName()); + assertEquals(2, process.getAllSteps().size()); + + QBackendStepMetaData myBackendStep = process.getBackendStep("myBackendStep"); + assertNotNull(myBackendStep, "myBackendStep should not be null"); + // todo - propagate this? assertEquals("myBackendStep", myBackendStep.getName()); + assertEquals("com.kingsrook.test.processes.MyBackendStep", myBackendStep.getCode().getName()); + + QFrontendStepMetaData myFrontendStep = process.getFrontendStep("myFrontendStep"); + assertNotNull(myFrontendStep, "myFrontendStep should not be null"); + assertEquals(2, myFrontendStep.getComponents().size()); + assertEquals(QComponentType.HELP_TEXT, myFrontendStep.getComponents().get(0).getType()); + assertEquals(Map.of("foo", "bar"), myFrontendStep.getComponents().get(0).getValues()); + assertEquals(QComponentType.VIEW_FORM, myFrontendStep.getComponents().get(1).getType()); + + assertEquals(2, myFrontendStep.getViewFields().size()); + assertEquals("myField", myFrontendStep.getViewFields().get(0).getName()); + assertEquals(QFieldType.STRING, myFrontendStep.getViewFields().get(0).getType()); + assertEquals("yourField", myFrontendStep.getViewFields().get(1).getName()); + assertEquals(QFieldType.DATE, myFrontendStep.getViewFields().get(1).getType()); + } + +} \ No newline at end of file