diff --git a/src/main/java/com/kingsrook/qqq/backend/core/actions/MetaDataAction.java b/src/main/java/com/kingsrook/qqq/backend/core/actions/MetaDataAction.java index ede2b4e7..0e9edb0b 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/actions/MetaDataAction.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/actions/MetaDataAction.java @@ -59,7 +59,7 @@ public class MetaDataAction Map processes = new LinkedHashMap<>(); for(Map.Entry entry : metaDataRequest.getInstance().getProcesses().entrySet()) { - processes.put(entry.getKey(), new QFrontendProcessMetaData(entry.getValue())); + processes.put(entry.getKey(), new QFrontendProcessMetaData(entry.getValue(), false)); } metaDataResult.setProcesses(processes); diff --git a/src/main/java/com/kingsrook/qqq/backend/core/actions/ProcessMetaDataAction.java b/src/main/java/com/kingsrook/qqq/backend/core/actions/ProcessMetaDataAction.java new file mode 100644 index 00000000..4d721de1 --- /dev/null +++ b/src/main/java/com/kingsrook/qqq/backend/core/actions/ProcessMetaDataAction.java @@ -0,0 +1,60 @@ +/* + * 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; + + +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException; +import com.kingsrook.qqq.backend.core.model.actions.metadata.process.ProcessMetaDataRequest; +import com.kingsrook.qqq.backend.core.model.actions.metadata.process.ProcessMetaDataResult; +import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendProcessMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; + + +/******************************************************************************* + ** Action to fetch meta-data for a process. + ** + *******************************************************************************/ +public class ProcessMetaDataAction +{ + /******************************************************************************* + ** + *******************************************************************************/ + public ProcessMetaDataResult execute(ProcessMetaDataRequest processMetaDataRequest) throws QException + { + ActionHelper.validateSession(processMetaDataRequest); + + // todo pre-customization - just get to modify the request? + ProcessMetaDataResult processMetaDataResult = new ProcessMetaDataResult(); + + QProcessMetaData process = processMetaDataRequest.getInstance().getProcess(processMetaDataRequest.getProcessName()); + if(process == null) + { + throw (new QNotFoundException("Process [" + processMetaDataRequest.getProcessName() + "] was not found.")); + } + processMetaDataResult.setProcess(new QFrontendProcessMetaData(process, true)); + + // todo post-customization - can do whatever w/ the result if you want + + return processMetaDataResult; + } +} diff --git a/src/main/java/com/kingsrook/qqq/backend/core/actions/RunFunctionAction.java b/src/main/java/com/kingsrook/qqq/backend/core/actions/RunBackendStepAction.java similarity index 61% rename from src/main/java/com/kingsrook/qqq/backend/core/actions/RunFunctionAction.java rename to src/main/java/com/kingsrook/qqq/backend/core/actions/RunBackendStepAction.java index 58ce72c0..fba23184 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/actions/RunFunctionAction.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/actions/RunBackendStepAction.java @@ -28,15 +28,16 @@ import java.util.List; import java.util.Map; import com.kingsrook.qqq.backend.core.callbacks.QProcessCallback; import com.kingsrook.qqq.backend.core.exceptions.QException; -import com.kingsrook.qqq.backend.core.interfaces.FunctionBody; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionRequest; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionResult; +import com.kingsrook.qqq.backend.core.interfaces.BackendStep; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepRequest; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResult; import com.kingsrook.qqq.backend.core.model.actions.query.QueryRequest; import com.kingsrook.qqq.backend.core.model.actions.query.QueryResult; import com.kingsrook.qqq.backend.core.model.metadata.QCodeReference; import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMetaData; -import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import org.apache.logging.log4j.LogManager; @@ -44,54 +45,61 @@ import org.apache.logging.log4j.Logger; /******************************************************************************* - ** Action handler for running q-functions. + ** Action handler for running backend steps as part of processes. * *******************************************************************************/ -public class RunFunctionAction +public class RunBackendStepAction { - private static final Logger LOG = LogManager.getLogger(RunFunctionAction.class); + private static final Logger LOG = LogManager.getLogger(RunBackendStepAction.class); + + /******************************************************************************* ** *******************************************************************************/ - public RunFunctionResult execute(RunFunctionRequest runFunctionRequest) throws QException + public RunBackendStepResult execute(RunBackendStepRequest runBackendStepRequest) throws QException { - ActionHelper.validateSession(runFunctionRequest); + ActionHelper.validateSession(runBackendStepRequest); - QProcessMetaData process = runFunctionRequest.getInstance().getProcess(runFunctionRequest.getProcessName()); + QProcessMetaData process = runBackendStepRequest.getInstance().getProcess(runBackendStepRequest.getProcessName()); if(process == null) { - throw new QException("Process [" + runFunctionRequest.getProcessName() + "] is not defined in this instance."); + throw new QException("Process [" + runBackendStepRequest.getProcessName() + "] is not defined in this instance."); } - QFunctionMetaData function = process.getFunction(runFunctionRequest.getFunctionName()); - if(function == null) + QStepMetaData stepMetaData = process.getStep(runBackendStepRequest.getStepName()); + if(stepMetaData == null) { - throw new QException("Function [" + runFunctionRequest.getFunctionName() + "] is not defined in the process [" + process.getName() + "]"); + throw new QException("Step [" + runBackendStepRequest.getStepName() + "] is not defined in the process [" + process.getName() + "]"); + } + + if(!(stepMetaData instanceof QBackendStepMetaData backendStepMetaData)) + { + throw new QException("Step [" + runBackendStepRequest.getStepName() + "] is not a backend step."); } ////////////////////////////////////////////////////////////////////////////////////// // ensure input data is set as needed - use callback object to get anything missing // ////////////////////////////////////////////////////////////////////////////////////// - ensureRecordsAreInRequest(runFunctionRequest, function); - ensureInputFieldsAreInRequest(runFunctionRequest, function); + ensureRecordsAreInRequest(runBackendStepRequest, backendStepMetaData); + ensureInputFieldsAreInRequest(runBackendStepRequest, backendStepMetaData); //////////////////////////////////////////////////////////////////// // load and run the user-defined code that actually does the work // //////////////////////////////////////////////////////////////////// - return (runFunctionBodyCode(function.getCode(), runFunctionRequest)); + return (runStepCode(backendStepMetaData.getCode(), runBackendStepRequest)); } /******************************************************************************* - ** check if this function needs any input fields - and if so, if we need to get one + ** check if this step needs any input fields - and if so, if we need to get one ** via the callback ** *******************************************************************************/ - private void ensureInputFieldsAreInRequest(RunFunctionRequest runFunctionRequest, QFunctionMetaData function) throws QException + private void ensureInputFieldsAreInRequest(RunBackendStepRequest runBackendStepRequest, QBackendStepMetaData step) throws QException { - QFunctionInputMetaData inputMetaData = function.getInputMetaData(); + QFunctionInputMetaData inputMetaData = step.getInputMetaData(); if(inputMetaData == null) { return; @@ -100,12 +108,12 @@ public class RunFunctionAction List fieldsToGet = new ArrayList<>(); for(QFieldMetaData field : inputMetaData.getFieldList()) { - Serializable value = runFunctionRequest.getValue(field.getName()); + Serializable value = runBackendStepRequest.getValue(field.getName()); if(value == null) { if(field.getDefaultValue() != null) { - runFunctionRequest.addValue(field.getName(), field.getDefaultValue()); + runBackendStepRequest.addValue(field.getName(), field.getDefaultValue()); } else { @@ -117,7 +125,7 @@ public class RunFunctionAction if(!fieldsToGet.isEmpty()) { - QProcessCallback callback = runFunctionRequest.getCallback(); + QProcessCallback callback = runBackendStepRequest.getCallback(); if(callback == null) { throw (new QException("Function is missing values for fields, but no callback was present to request fields from a user")); @@ -126,7 +134,7 @@ public class RunFunctionAction Map fieldValues = callback.getFieldValues(fieldsToGet); for(Map.Entry entry : fieldValues.entrySet()) { - runFunctionRequest.addValue(entry.getKey(), entry.getValue()); + runBackendStepRequest.addValue(entry.getKey(), entry.getValue()); // todo - check to make sure got values back? } } @@ -135,25 +143,25 @@ public class RunFunctionAction /******************************************************************************* - ** check if this function uses a record list - and if so, if we need to get one + ** check if this step uses a record list - and if so, if we need to get one ** via the callback *******************************************************************************/ - private void ensureRecordsAreInRequest(RunFunctionRequest runFunctionRequest, QFunctionMetaData function) throws QException + private void ensureRecordsAreInRequest(RunBackendStepRequest runBackendStepRequest, QBackendStepMetaData step) throws QException { - QFunctionInputMetaData inputMetaData = function.getInputMetaData(); + QFunctionInputMetaData inputMetaData = step.getInputMetaData(); if(inputMetaData != null && inputMetaData.getRecordListMetaData() != null) { - if(CollectionUtils.nullSafeIsEmpty(runFunctionRequest.getRecords())) + if(CollectionUtils.nullSafeIsEmpty(runBackendStepRequest.getRecords())) { - QueryRequest queryRequest = new QueryRequest(runFunctionRequest.getInstance()); - queryRequest.setSession(runFunctionRequest.getSession()); + QueryRequest queryRequest = new QueryRequest(runBackendStepRequest.getInstance()); + queryRequest.setSession(runBackendStepRequest.getSession()); queryRequest.setTableName(inputMetaData.getRecordListMetaData().getTableName()); // todo - handle this being async (e.g., http) // seems like it just needs to throw, breaking this flow, and to send a response to the frontend, directing it to prompt the user for the needed data - // then this function can re-run, hopefully with the needed data. + // then this step can re-run, hopefully with the needed data. - QProcessCallback callback = runFunctionRequest.getCallback(); + QProcessCallback callback = runBackendStepRequest.getCallback(); if(callback == null) { throw (new QException("Function is missing input records, but no callback was present to get a query filter from a user")); @@ -162,7 +170,7 @@ public class RunFunctionAction queryRequest.setFilter(callback.getQueryFilter()); QueryResult queryResult = new QueryAction().execute(queryRequest); - runFunctionRequest.setRecords(queryResult.getRecords()); + runBackendStepRequest.setRecords(queryResult.getRecords()); // todo - handle 0 results found? } } @@ -173,29 +181,29 @@ public class RunFunctionAction /******************************************************************************* ** *******************************************************************************/ - private RunFunctionResult runFunctionBodyCode(QCodeReference code, RunFunctionRequest runFunctionRequest) + private RunBackendStepResult runStepCode(QCodeReference code, RunBackendStepRequest runBackendStepRequest) { - RunFunctionResult runFunctionResult = new RunFunctionResult(); + RunBackendStepResult runBackendStepResult = new RunBackendStepResult(); try { - runFunctionResult.seedFromRequest(runFunctionRequest); + runBackendStepResult.seedFromRequest(runBackendStepRequest); Class codeClass = Class.forName(code.getName()); Object codeObject = codeClass.getConstructor().newInstance(); - if(!(codeObject instanceof FunctionBody functionBodyCodeObject)) + if(!(codeObject instanceof BackendStep backendStepCodeObject)) { throw (new QException("The supplied code [" + codeClass.getName() + "] is not an instance of FunctionBody")); } - functionBodyCodeObject.run(runFunctionRequest, runFunctionResult); + backendStepCodeObject.run(runBackendStepRequest, runBackendStepResult); } catch(Exception e) { - runFunctionResult = new RunFunctionResult(); - runFunctionResult.setError("Error running function code: " + e.getMessage()); - LOG.info("Error running function code", e); + runBackendStepResult = new RunBackendStepResult(); + runBackendStepResult.setError("Error running backend step code: " + e.getMessage()); + LOG.info("Error running backend step code", e); } - return (runFunctionResult); + return (runBackendStepResult); } } diff --git a/src/main/java/com/kingsrook/qqq/backend/core/actions/RunProcessAction.java b/src/main/java/com/kingsrook/qqq/backend/core/actions/RunProcessAction.java index fb37ef29..57129ad3 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/actions/RunProcessAction.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/actions/RunProcessAction.java @@ -26,12 +26,12 @@ import java.util.List; import java.util.Optional; import com.kingsrook.qqq.backend.core.exceptions.QException; import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessState; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionRequest; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionResult; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepRequest; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResult; import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessRequest; import com.kingsrook.qqq.backend.core.model.actions.processes.RunProcessResult; -import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData; import com.kingsrook.qqq.backend.core.state.InMemoryStateProvider; import com.kingsrook.qqq.backend.core.state.StateProviderInterface; import com.kingsrook.qqq.backend.core.state.UUIDStateKey; @@ -59,35 +59,35 @@ public class RunProcessAction RunProcessResult runProcessResult = new RunProcessResult(); - UUIDStateKey stateKey = new UUIDStateKey(); - RunFunctionResult lastFunctionResult = null; + UUIDStateKey stateKey = new UUIDStateKey(); + RunBackendStepResult lastFunctionResult = null; // todo - custom routing? - List functionList = process.getFunctionList(); - for(QFunctionMetaData function : functionList) + List functionList = process.getStepList(); + for(QStepMetaData function : functionList) { - RunFunctionRequest runFunctionRequest = new RunFunctionRequest(runProcessRequest.getInstance()); + RunBackendStepRequest runBackendStepRequest = new RunBackendStepRequest(runProcessRequest.getInstance()); if(lastFunctionResult == null) { /////////////////////////////////////////////////////////////////////////////////////////////////////// // for the first request, load state from the run process request to prime the run function request. // /////////////////////////////////////////////////////////////////////////////////////////////////////// - primeFunction(runProcessRequest, runFunctionRequest); + primeFunction(runProcessRequest, runBackendStepRequest); } else { //////////////////////////////////////////////////////////////////////////////////////// // for functions after the first one, load from state management to prime the request // //////////////////////////////////////////////////////////////////////////////////////// - loadState(stateKey, runFunctionRequest); + loadState(stateKey, runBackendStepRequest); } - runFunctionRequest.setProcessName(process.getName()); - runFunctionRequest.setFunctionName(function.getName()); - runFunctionRequest.setSession(runProcessRequest.getSession()); - runFunctionRequest.setCallback(runProcessRequest.getCallback()); - lastFunctionResult = new RunFunctionAction().execute(runFunctionRequest); + runBackendStepRequest.setProcessName(process.getName()); + runBackendStepRequest.setStepName(function.getName()); + runBackendStepRequest.setSession(runProcessRequest.getSession()); + runBackendStepRequest.setCallback(runProcessRequest.getCallback()); + lastFunctionResult = new RunBackendStepAction().execute(runBackendStepRequest); if(lastFunctionResult.getError() != null) { runProcessResult.setError(lastFunctionResult.getError()); @@ -116,7 +116,7 @@ public class RunProcessAction // TODO - read this from somewhere in meta data eh? return InMemoryStateProvider.getInstance(); - // TODO - by using JSON serialization internally, this makes stupidly large payloads and crashes things. + // todo - by using JSON serialization internally, this makes stupidly large payloads and crashes things. // return TempFileStateProvider.getInstance(); } @@ -126,9 +126,9 @@ public class RunProcessAction ** Store the process state from a function result to the state provider ** *******************************************************************************/ - private void storeState(UUIDStateKey stateKey, RunFunctionResult runFunctionResult) + private void storeState(UUIDStateKey stateKey, RunBackendStepResult runBackendStepResult) { - getStateProvider().put(stateKey, runFunctionResult.getProcessState()); + getStateProvider().put(stateKey, runBackendStepResult.getProcessState()); } @@ -137,9 +137,9 @@ public class RunProcessAction ** Copy data (the state) down from the run-process request, down into the run- ** function request. *******************************************************************************/ - private void primeFunction(RunProcessRequest runProcessRequest, RunFunctionRequest runFunctionRequest) + private void primeFunction(RunProcessRequest runProcessRequest, RunBackendStepRequest runBackendStepRequest) { - runFunctionRequest.seedFromRunProcessRequest(runProcessRequest); + runBackendStepRequest.seedFromRunProcessRequest(runProcessRequest); } @@ -148,10 +148,10 @@ public class RunProcessAction ** Load the process state into a function request from the state provider ** *******************************************************************************/ - private void loadState(UUIDStateKey stateKey, RunFunctionRequest runFunctionRequest) throws QException + private void loadState(UUIDStateKey stateKey, RunBackendStepRequest runBackendStepRequest) throws QException { Optional processState = getStateProvider().get(ProcessState.class, stateKey); - runFunctionRequest.seedFromProcessState(processState + runBackendStepRequest.seedFromProcessState(processState .orElseThrow(() -> new QException("Could not find process state in state provider."))); } diff --git a/src/main/java/com/kingsrook/qqq/backend/core/actions/TableMetaDataAction.java b/src/main/java/com/kingsrook/qqq/backend/core/actions/TableMetaDataAction.java index 21a868d5..9b887769 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/actions/TableMetaDataAction.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/actions/TableMetaDataAction.java @@ -23,7 +23,7 @@ package com.kingsrook.qqq.backend.core.actions; import com.kingsrook.qqq.backend.core.exceptions.QException; -import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException; +import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException; import com.kingsrook.qqq.backend.core.model.actions.metadata.table.TableMetaDataRequest; import com.kingsrook.qqq.backend.core.model.actions.metadata.table.TableMetaDataResult; import com.kingsrook.qqq.backend.core.model.metadata.QTableMetaData; @@ -49,7 +49,7 @@ public class TableMetaDataAction QTableMetaData table = tableMetaDataRequest.getInstance().getTable(tableMetaDataRequest.getTableName()); if(table == null) { - throw (new QUserFacingException("Table [" + tableMetaDataRequest.getTableName() + "] was not found.")); + throw (new QNotFoundException("Table [" + tableMetaDataRequest.getTableName() + "] was not found.")); } tableMetaDataResult.setTable(new QFrontendTableMetaData(table, true)); diff --git a/src/main/java/com/kingsrook/qqq/backend/core/exceptions/QNotFoundException.java b/src/main/java/com/kingsrook/qqq/backend/core/exceptions/QNotFoundException.java new file mode 100644 index 00000000..e33853bc --- /dev/null +++ b/src/main/java/com/kingsrook/qqq/backend/core/exceptions/QNotFoundException.java @@ -0,0 +1,54 @@ +/* + * 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.exceptions; + + +/******************************************************************************* + ** User-facing exception for when something wasn't found (e.g., a named table or + ** record-by-id). + ** + *******************************************************************************/ +public class QNotFoundException extends QUserFacingException +{ + + + /******************************************************************************* + ** Constructor of message + ** + *******************************************************************************/ + public QNotFoundException(String message) + { + super(message); + } + + + + /******************************************************************************* + ** Constructor of message & cause + ** + *******************************************************************************/ + public QNotFoundException(String message, Throwable cause) + { + super(message, cause); + } + +} diff --git a/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceEnricher.java b/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceEnricher.java index 3cc63e4c..67d1a4d1 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceEnricher.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/instances/QInstanceEnricher.java @@ -27,7 +27,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData; import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.QTableMetaData; -import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; import com.kingsrook.qqq.backend.core.utils.StringUtils; @@ -100,9 +100,9 @@ public class QInstanceEnricher process.setLabel(nameToLabel(process.getName())); } - if(process.getFunctionList() != null) + if(process.getStepList() != null) { - process.getFunctionList().forEach(this::enrich); + process.getStepList().forEach(this::enrich); } } @@ -111,7 +111,7 @@ public class QInstanceEnricher /******************************************************************************* ** *******************************************************************************/ - private void enrich(QFunctionMetaData function) + private void enrich(QStepMetaData function) { if(!StringUtils.hasContent(function.getLabel())) { diff --git a/src/main/java/com/kingsrook/qqq/backend/core/interfaces/FunctionBody.java b/src/main/java/com/kingsrook/qqq/backend/core/interfaces/BackendStep.java similarity index 82% rename from src/main/java/com/kingsrook/qqq/backend/core/interfaces/FunctionBody.java rename to src/main/java/com/kingsrook/qqq/backend/core/interfaces/BackendStep.java index 12310ee5..54305106 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/interfaces/FunctionBody.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/interfaces/BackendStep.java @@ -23,22 +23,22 @@ package com.kingsrook.qqq.backend.core.interfaces; import com.kingsrook.qqq.backend.core.exceptions.QException; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionRequest; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionResult; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepRequest; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResult; /******************************************************************************* - ** Simple interface that a "custom" function (as in, a component of a Process) - ** must implement. + ** Simple interface that Backend Steps (e.g., code within processes) must implement + ** *******************************************************************************/ -public interface FunctionBody +public interface BackendStep { /******************************************************************************* - ** Execute the function - using the request as input, and the result as output. + ** Execute the backend step - using the request as input, and the result as output. ** ** TODO - think about - why take the Result object as a param, instead of return it? ** Is this way easier for inter-language operability maybe? * Also - there's way too much "process-specific gunk" in the Request object - can we simplify it? *******************************************************************************/ - void run(RunFunctionRequest runFunctionRequest, RunFunctionResult runFunctionResult) throws QException; + void run(RunBackendStepRequest runBackendStepRequest, RunBackendStepResult runBackendStepResult) throws QException; } diff --git a/src/main/java/com/kingsrook/qqq/backend/core/interfaces/mock/MockFunctionBody.java b/src/main/java/com/kingsrook/qqq/backend/core/interfaces/mock/MockBackendStep.java similarity index 64% rename from src/main/java/com/kingsrook/qqq/backend/core/interfaces/mock/MockFunctionBody.java rename to src/main/java/com/kingsrook/qqq/backend/core/interfaces/mock/MockBackendStep.java index 93b677f3..bb2e8bbe 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/interfaces/mock/MockFunctionBody.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/interfaces/mock/MockBackendStep.java @@ -22,9 +22,9 @@ package com.kingsrook.qqq.backend.core.interfaces.mock; -import com.kingsrook.qqq.backend.core.interfaces.FunctionBody; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionRequest; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionResult; +import com.kingsrook.qqq.backend.core.interfaces.BackendStep; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepRequest; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResult; /******************************************************************************* @@ -32,19 +32,22 @@ import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionResult; ** ** Basically just passes data from the request to the response. *******************************************************************************/ -public class MockFunctionBody implements FunctionBody +public class MockBackendStep implements BackendStep { - @Override - public void run(RunFunctionRequest runFunctionRequest, RunFunctionResult runFunctionResult) - { - runFunctionResult.getRecords().forEach(r -> r.setValue("mockValue", "Ha ha!")); + public final static String FIELD_GREETING_PREFIX = "greetingPrefix"; + public final static String FIELD_GREETING_SUFFIX = "greetingSuffix"; - runFunctionResult.setValues(runFunctionRequest.getValues()); - runFunctionResult.addValue("mockValue", "You so silly"); + @Override + public void run(RunBackendStepRequest runBackendStepRequest, RunBackendStepResult runBackendStepResult) + { + runBackendStepResult.getRecords().forEach(r -> r.setValue("mockValue", "Ha ha!")); + + runBackendStepResult.setValues(runBackendStepRequest.getValues()); + runBackendStepResult.addValue("mockValue", "You so silly"); ///////////////////////////////// // mock the "greet" process... // ///////////////////////////////// - runFunctionResult.addValue("outputMessage", runFunctionRequest.getValueString("greetingPrefix") + " X " + runFunctionRequest.getValueString("greetingSuffix")); + runBackendStepResult.addValue("outputMessage", runBackendStepRequest.getValueString(FIELD_GREETING_PREFIX) + " X " + runBackendStepRequest.getValueString(FIELD_GREETING_SUFFIX)); } } diff --git a/src/main/java/com/kingsrook/qqq/backend/core/model/actions/metadata/process/ProcessMetaDataRequest.java b/src/main/java/com/kingsrook/qqq/backend/core/model/actions/metadata/process/ProcessMetaDataRequest.java new file mode 100644 index 00000000..c7e39a47 --- /dev/null +++ b/src/main/java/com/kingsrook/qqq/backend/core/model/actions/metadata/process/ProcessMetaDataRequest.java @@ -0,0 +1,77 @@ +/* + * 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.model.actions.metadata.process; + + +import com.kingsrook.qqq.backend.core.model.actions.AbstractQRequest; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; + + +/******************************************************************************* + ** Request for meta-data for a process. + ** + *******************************************************************************/ +public class ProcessMetaDataRequest extends AbstractQRequest +{ + private String processName; + + + + /******************************************************************************* + ** + *******************************************************************************/ + public ProcessMetaDataRequest() + { + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + public ProcessMetaDataRequest(QInstance instance) + { + super(instance); + } + + + + /******************************************************************************* + ** Getter for processName + ** + *******************************************************************************/ + public String getProcessName() + { + return processName; + } + + + + /******************************************************************************* + ** Setter for processName + ** + *******************************************************************************/ + public void setProcessName(String processName) + { + this.processName = processName; + } +} diff --git a/src/main/java/com/kingsrook/qqq/backend/core/model/actions/metadata/process/ProcessMetaDataResult.java b/src/main/java/com/kingsrook/qqq/backend/core/model/actions/metadata/process/ProcessMetaDataResult.java new file mode 100644 index 00000000..385955b6 --- /dev/null +++ b/src/main/java/com/kingsrook/qqq/backend/core/model/actions/metadata/process/ProcessMetaDataResult.java @@ -0,0 +1,58 @@ +/* + * 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.model.actions.metadata.process; + + +import com.kingsrook.qqq.backend.core.model.actions.AbstractQResult; +import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendProcessMetaData; + + +/******************************************************************************* + * Result for a process-metaData action + * + *******************************************************************************/ +public class ProcessMetaDataResult extends AbstractQResult +{ + QFrontendProcessMetaData process; + + + + /******************************************************************************* + ** Getter for process + ** + *******************************************************************************/ + public QFrontendProcessMetaData getProcess() + { + return process; + } + + + + /******************************************************************************* + ** Setter for process + ** + *******************************************************************************/ + public void setProcess(QFrontendProcessMetaData process) + { + this.process = process; + } +} diff --git a/src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunFunctionRequest.java b/src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunBackendStepRequest.java similarity index 90% rename from src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunFunctionRequest.java rename to src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunBackendStepRequest.java index 6b8701b7..b3d6e0b9 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunFunctionRequest.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunBackendStepRequest.java @@ -29,18 +29,18 @@ import com.kingsrook.qqq.backend.core.callbacks.QProcessCallback; import com.kingsrook.qqq.backend.core.model.actions.AbstractQRequest; import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.model.metadata.QInstance; -import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData; /******************************************************************************* - ** Request data container for the RunFunction action + ** Request data container for the RunBackendStep action ** *******************************************************************************/ -public class RunFunctionRequest extends AbstractQRequest +public class RunBackendStepRequest extends AbstractQRequest { private ProcessState processState; private String processName; - private String functionName; + private String stepName; private QProcessCallback callback; @@ -48,7 +48,7 @@ public class RunFunctionRequest extends AbstractQRequest /******************************************************************************* ** *******************************************************************************/ - public RunFunctionRequest() + public RunBackendStepRequest() { processState = new ProcessState(); } @@ -58,7 +58,7 @@ public class RunFunctionRequest extends AbstractQRequest /******************************************************************************* ** *******************************************************************************/ - public RunFunctionRequest(QInstance instance) + public RunBackendStepRequest(QInstance instance) { super(instance); processState = new ProcessState(); @@ -91,9 +91,9 @@ public class RunFunctionRequest extends AbstractQRequest /******************************************************************************* ** *******************************************************************************/ - public QFunctionMetaData getFunctionMetaData() + public QStepMetaData getStepMetaData() { - return (instance.getFunction(getProcessName(), getFunctionName())); + return (instance.getProcessStep(getProcessName(), getStepName())); } @@ -124,7 +124,7 @@ public class RunFunctionRequest extends AbstractQRequest ** Setter for processName ** *******************************************************************************/ - public RunFunctionRequest withProcessName(String processName) + public RunBackendStepRequest withProcessName(String processName) { this.processName = processName; return (this); @@ -136,9 +136,9 @@ public class RunFunctionRequest extends AbstractQRequest ** Getter for functionName ** *******************************************************************************/ - public String getFunctionName() + public String getStepName() { - return functionName; + return stepName; } @@ -147,9 +147,9 @@ public class RunFunctionRequest extends AbstractQRequest ** Setter for functionName ** *******************************************************************************/ - public void setFunctionName(String functionName) + public void setStepName(String stepName) { - this.functionName = functionName; + this.stepName = stepName; } @@ -158,9 +158,9 @@ public class RunFunctionRequest extends AbstractQRequest ** Setter for functionName ** *******************************************************************************/ - public RunFunctionRequest withFunctionName(String functionName) + public RunBackendStepRequest withFunctionName(String functionName) { - this.functionName = functionName; + this.stepName = functionName; return (this); } @@ -192,7 +192,7 @@ public class RunFunctionRequest extends AbstractQRequest ** Setter for records ** *******************************************************************************/ - public RunFunctionRequest withRecords(List records) + public RunBackendStepRequest withRecords(List records) { this.processState.setRecords(records); return (this); @@ -226,7 +226,7 @@ public class RunFunctionRequest extends AbstractQRequest ** Setter for values ** *******************************************************************************/ - public RunFunctionRequest withValues(Map values) + public RunBackendStepRequest withValues(Map values) { this.processState.setValues(values); return (this); @@ -238,7 +238,7 @@ public class RunFunctionRequest extends AbstractQRequest ** Setter for values ** *******************************************************************************/ - public RunFunctionRequest addValue(String fieldName, Serializable value) + public RunBackendStepRequest addValue(String fieldName, Serializable value) { this.processState.getValues().put(fieldName, value); return (this); @@ -272,7 +272,7 @@ public class RunFunctionRequest extends AbstractQRequest ** Setter for callback ** *******************************************************************************/ - public RunFunctionRequest withCallback(QProcessCallback callback) + public RunBackendStepRequest withCallback(QProcessCallback callback) { this.callback = callback; return (this); diff --git a/src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunFunctionResult.java b/src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunBackendStepResult.java similarity index 90% rename from src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunFunctionResult.java rename to src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunBackendStepResult.java index 5d4653c2..05838801 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunFunctionResult.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunBackendStepResult.java @@ -30,10 +30,10 @@ import com.kingsrook.qqq.backend.core.model.data.QRecord; /******************************************************************************* - ** Result data container for the RunFunction action + ** Result data container for the RunBackendStep action ** *******************************************************************************/ -public class RunFunctionResult extends AbstractQResult +public class RunBackendStepResult extends AbstractQResult { private ProcessState processState; private String error; @@ -46,7 +46,7 @@ public class RunFunctionResult extends AbstractQResult @Override public String toString() { - return "RunFunctionResult{error='" + error + return "RunBackendStepResult{error='" + error + ",records.size()=" + (processState == null ? null : processState.getRecords().size()) + ",values=" + (processState == null ? null : processState.getValues()) + "}"; @@ -57,7 +57,7 @@ public class RunFunctionResult extends AbstractQResult /******************************************************************************* ** *******************************************************************************/ - public RunFunctionResult() + public RunBackendStepResult() { this.processState = new ProcessState(); } @@ -68,9 +68,9 @@ public class RunFunctionResult extends AbstractQResult ** e.g., populate the process state (records, values) in this result object. ** *******************************************************************************/ - public void seedFromRequest(RunFunctionRequest runFunctionRequest) + public void seedFromRequest(RunBackendStepRequest runBackendStepRequest) { - this.processState = runFunctionRequest.getProcessState(); + this.processState = runBackendStepRequest.getProcessState(); } @@ -101,7 +101,7 @@ public class RunFunctionResult extends AbstractQResult ** Setter for records ** *******************************************************************************/ - public RunFunctionResult withRecords(List records) + public RunBackendStepResult withRecords(List records) { this.processState.setRecords(records); return (this); @@ -135,7 +135,7 @@ public class RunFunctionResult extends AbstractQResult ** Setter for values ** *******************************************************************************/ - public RunFunctionResult withValues(Map values) + public RunBackendStepResult withValues(Map values) { this.processState.setValues(values); return (this); @@ -147,7 +147,7 @@ public class RunFunctionResult extends AbstractQResult ** Setter for values ** *******************************************************************************/ - public RunFunctionResult addValue(String fieldName, Serializable value) + public RunBackendStepResult addValue(String fieldName, Serializable value) { this.processState.getValues().put(fieldName, value); return (this); diff --git a/src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunProcessResult.java b/src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunProcessResult.java index 7415563d..174159bd 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunProcessResult.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/model/actions/processes/RunProcessResult.java @@ -69,9 +69,9 @@ public class RunProcessResult extends AbstractQResult ** the final function result ** *******************************************************************************/ - public void seedFromLastFunctionResult(RunFunctionResult runFunctionResult) + public void seedFromLastFunctionResult(RunBackendStepResult runBackendStepResult) { - this.processState = runFunctionResult.getProcessState(); + this.processState = runBackendStepResult.getProcessState(); } diff --git a/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java b/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java index 04e0ba4d..e7491002 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/QInstance.java @@ -29,7 +29,7 @@ import java.util.Map; import com.fasterxml.jackson.annotation.JsonIgnore; import com.kingsrook.qqq.backend.core.instances.QInstanceValidationKey; import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource; -import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; @@ -211,7 +211,7 @@ public class QInstance /******************************************************************************* ** *******************************************************************************/ - public QFunctionMetaData getFunction(String processName, String functionName) + public QStepMetaData getProcessStep(String processName, String functionName) { QProcessMetaData qProcessMetaData = this.processes.get(processName); if(qProcessMetaData == null) @@ -219,7 +219,7 @@ public class QInstance return (null); } - return (qProcessMetaData.getFunction(functionName)); + return (qProcessMetaData.getStep(functionName)); } diff --git a/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendProcessMetaData.java b/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendProcessMetaData.java index 0fb14099..7de6a688 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendProcessMetaData.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendProcessMetaData.java @@ -22,10 +22,14 @@ package com.kingsrook.qqq.backend.core.model.metadata.frontend; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; +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; /******************************************************************************* @@ -39,7 +43,8 @@ public class QFrontendProcessMetaData private String name; private String label; private String tableName; - private Map fields; + + private List frontendSteps; ////////////////////////////////////////////////////////////////////////////////// // do not add setters. take values from the source-object in the constructor!! // @@ -50,11 +55,26 @@ public class QFrontendProcessMetaData /******************************************************************************* ** *******************************************************************************/ - public QFrontendProcessMetaData(QProcessMetaData processMetaData) + public QFrontendProcessMetaData(QProcessMetaData processMetaData, boolean includeSteps) { this.name = processMetaData.getName(); this.label = processMetaData.getLabel(); this.tableName = processMetaData.getTableName(); + + if(includeSteps) + { + if(CollectionUtils.nullSafeHasContents(processMetaData.getStepList())) + { + this.frontendSteps = processMetaData.getStepList().stream() + .filter(QFrontendStepMetaData.class::isInstance) + .map(QFrontendStepMetaData.class::cast) + .collect(Collectors.toList()); + } + else + { + frontendSteps = new ArrayList<>(); + } + } } @@ -93,11 +113,22 @@ public class QFrontendProcessMetaData /******************************************************************************* - ** Getter for fields + ** Getter for frontendSteps ** *******************************************************************************/ - public Map getFields() + public List getFrontendSteps() { - return fields; + return frontendSteps; + } + + + + /******************************************************************************* + ** Setter for frontendSteps + ** + *******************************************************************************/ + public void setFrontendSteps(List frontendSteps) + { + this.frontendSteps = frontendSteps; } } diff --git a/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QFunctionMetaData.java b/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QBackendStepMetaData.java similarity index 65% rename from src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QFunctionMetaData.java rename to src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QBackendStepMetaData.java index 40980c33..c6fcb64c 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QFunctionMetaData.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QBackendStepMetaData.java @@ -24,67 +24,21 @@ package com.kingsrook.qqq.backend.core.model.metadata.processes; import java.util.ArrayList; import java.util.List; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.kingsrook.qqq.backend.core.model.metadata.QCodeReference; import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData; /******************************************************************************* - ** Meta-Data to define a function in a QQQ instance. + ** Meta-Data to define a backend-step in a process in a QQQ instance. e.g., + ** code that runs on a server/backend, to do something to some data. ** *******************************************************************************/ -public class QFunctionMetaData +public class QBackendStepMetaData extends QStepMetaData { - private String name; - private String label; private QFunctionInputMetaData inputMetaData; private QFunctionOutputMetaData outputMetaData; private QCodeReference code; - private QOutputView outputView; - - - - /******************************************************************************* - ** Getter for name - ** - *******************************************************************************/ - public String getName() - { - return name; - } - - - - /******************************************************************************* - ** Setter for name - ** - *******************************************************************************/ - public void setName(String name) - { - this.name = name; - } - - - - /******************************************************************************* - ** Setter for name - ** - *******************************************************************************/ - public QFunctionMetaData withName(String name) - { - this.name = name; - return (this); - } - - - - /******************************************************************************* - ** Getter for label - ** - *******************************************************************************/ - public String getLabel() - { - return label; - } @@ -92,20 +46,10 @@ public class QFunctionMetaData ** Setter for label ** *******************************************************************************/ - public void setLabel(String label) + @Override + public QBackendStepMetaData withName(String name) { - this.label = label; - } - - - - /******************************************************************************* - ** Setter for label - ** - *******************************************************************************/ - public QFunctionMetaData withLabel(String label) - { - this.label = label; + setName(name); return (this); } @@ -137,7 +81,7 @@ public class QFunctionMetaData ** Setter for inputData ** *******************************************************************************/ - public QFunctionMetaData withInputData(QFunctionInputMetaData inputData) + public QBackendStepMetaData withInputData(QFunctionInputMetaData inputData) { this.inputMetaData = inputData; return (this); @@ -171,7 +115,7 @@ public class QFunctionMetaData ** Setter for outputData ** *******************************************************************************/ - public QFunctionMetaData withOutputMetaData(QFunctionOutputMetaData outputMetaData) + public QBackendStepMetaData withOutputMetaData(QFunctionOutputMetaData outputMetaData) { this.outputMetaData = outputMetaData; return (this); @@ -205,7 +149,7 @@ public class QFunctionMetaData ** Setter for code ** *******************************************************************************/ - public QFunctionMetaData withCode(QCodeReference code) + public QBackendStepMetaData withCode(QCodeReference code) { this.code = code; return (this); @@ -213,43 +157,11 @@ public class QFunctionMetaData - /******************************************************************************* - ** Getter for outputView - ** - *******************************************************************************/ - public QOutputView getOutputView() - { - return outputView; - } - - - - /******************************************************************************* - ** Setter for outputView - ** - *******************************************************************************/ - public void setOutputView(QOutputView outputView) - { - this.outputView = outputView; - } - - - - /******************************************************************************* - ** Setter for outputView - ** - *******************************************************************************/ - public QFunctionMetaData withOutputView(QOutputView outputView) - { - this.outputView = outputView; - return (this); - } - - - /******************************************************************************* ** Get a list of all of the input fields used by this function *******************************************************************************/ + @JsonIgnore + @Override public List getInputFields() { List rs = new ArrayList<>(); @@ -265,6 +177,8 @@ public class QFunctionMetaData /******************************************************************************* ** Get a list of all of the output fields used by this function *******************************************************************************/ + @JsonIgnore + @Override public List getOutputFields() { List rs = new ArrayList<>(); diff --git a/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QFrontendStepMetaData.java b/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QFrontendStepMetaData.java new file mode 100644 index 00000000..4f19e051 --- /dev/null +++ b/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QFrontendStepMetaData.java @@ -0,0 +1,115 @@ +/* + * 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.model.metadata.processes; + + +import java.util.ArrayList; +import java.util.List; +import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData; + + +/******************************************************************************* + ** Meta-Data to define a front-end step in a process in a QQQ instance (e.g., + ** a screen presented to a user). + ** + *******************************************************************************/ +public class QFrontendStepMetaData extends QStepMetaData +{ + private List formFields; + + + + /******************************************************************************* + ** Getter for formFields + ** + *******************************************************************************/ + public List getFormFields() + { + return formFields; + } + + + + /******************************************************************************* + ** Setter for formFields + ** + *******************************************************************************/ + public void setFormFields(List formFields) + { + this.formFields = formFields; + } + + + + /******************************************************************************* + ** fluent setter to add a single form field + ** + *******************************************************************************/ + public QFrontendStepMetaData withFormField(QFieldMetaData formField) + { + if(this.formFields == null) + { + this.formFields = new ArrayList<>(); + } + this.formFields.add(formField); + return (this); + } + + + + /******************************************************************************* + ** fluent setter for formFields + ** + *******************************************************************************/ + public QFrontendStepMetaData withFormFields(List formFields) + { + this.formFields = formFields; + return (this); + } + + + + /******************************************************************************* + ** fluent setter for name + ** + *******************************************************************************/ + @Override + public QFrontendStepMetaData withName(String name) + { + setName(name); + return (this); + } + + + + /******************************************************************************* + ** fluent setter for label + ** + *******************************************************************************/ + @Override + public QFrontendStepMetaData withLabel(String label) + { + setLabel(label); + return (this); + } + +} diff --git a/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QProcessMetaData.java b/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QProcessMetaData.java index 52a7cd32..6d726089 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QProcessMetaData.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QProcessMetaData.java @@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.core.model.metadata.processes; import java.util.ArrayList; import java.util.List; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData; @@ -33,10 +34,10 @@ import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData; *******************************************************************************/ public class QProcessMetaData { - private String name; - private String label; - private String tableName; - private List functionList; + private String name; + private String label; + private String tableName; + private List stepList; @@ -143,51 +144,51 @@ public class QProcessMetaData /******************************************************************************* - ** Getter for functionList + ** Getter for stepList ** *******************************************************************************/ - public List getFunctionList() + public List getStepList() { - return functionList; + return stepList; } /******************************************************************************* - ** Setter for functionList + ** Setter for stepList ** *******************************************************************************/ - public QProcessMetaData withFunctionList(List functionList) + public QProcessMetaData withStepList(List stepList) { - this.functionList = functionList; + this.stepList = stepList; return (this); } /******************************************************************************* - ** Setter for functionList + ** Setter for stepList ** *******************************************************************************/ - public QProcessMetaData addFunction(QFunctionMetaData function) + public QProcessMetaData addStep(QStepMetaData step) { - if(this.functionList == null) + if(this.stepList == null) { - this.functionList = new ArrayList<>(); + this.stepList = new ArrayList<>(); } - this.functionList.add(function); + this.stepList.add(step); return (this); } /******************************************************************************* - ** Setter for functionList + ** Setter for stepList ** *******************************************************************************/ - public void setFunctionList(List functionList) + public void setStepList(List stepList) { - this.functionList = functionList; + this.stepList = stepList; } @@ -195,13 +196,13 @@ public class QProcessMetaData /******************************************************************************* ** *******************************************************************************/ - public QFunctionMetaData getFunction(String functionName) + public QStepMetaData getStep(String stepName) { - for(QFunctionMetaData function : functionList) + for(QStepMetaData step : stepList) { - if(function.getName().equals(functionName)) + if(step.getName().equals(stepName)) { - return (function); + return (step); } } @@ -211,16 +212,27 @@ public class QProcessMetaData /******************************************************************************* - ** Get a list of all of the input fields used by all the functions in this process. + ** Wrapper to getStep, that internally casts t0 BackendStepMetaData *******************************************************************************/ + public QBackendStepMetaData getBackendStep(String name) + { + return (QBackendStepMetaData) getStep(name); + } + + + + /******************************************************************************* + ** Get a list of all of the input fields used by all the steps in this process. + *******************************************************************************/ + @JsonIgnore public List getInputFields() { List rs = new ArrayList<>(); - if(functionList != null) + if(stepList != null) { - for(QFunctionMetaData function : functionList) + for(QStepMetaData step : stepList) { - rs.addAll(function.getInputFields()); + rs.addAll(step.getInputFields()); } } return (rs); @@ -229,18 +241,20 @@ public class QProcessMetaData /******************************************************************************* - ** Get a list of all of the output fields used by all the functions in this process. + ** Get a list of all of the output fields used by all the steps in this process. *******************************************************************************/ + @JsonIgnore public List getOutputFields() { List rs = new ArrayList<>(); - if(functionList != null) + if(stepList != null) { - for(QFunctionMetaData function : functionList) + for(QStepMetaData step : stepList) { - rs.addAll(function.getOutputFields()); + rs.addAll(step.getOutputFields()); } } return (rs); } + } diff --git a/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QStepMetaData.java b/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QStepMetaData.java new file mode 100644 index 00000000..67e982b7 --- /dev/null +++ b/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/processes/QStepMetaData.java @@ -0,0 +1,130 @@ +/* + * 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.model.metadata.processes; + + +import java.util.ArrayList; +import java.util.List; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData; + + +/******************************************************************************* + ** Meta-Data to define a step in a process in a QQQ instance. + ** + *******************************************************************************/ +public class QStepMetaData +{ + private String name; + private String label; + + + + /******************************************************************************* + ** Getter for name + ** + *******************************************************************************/ + public String getName() + { + return name; + } + + + + /******************************************************************************* + ** Setter for name + ** + *******************************************************************************/ + public void setName(String name) + { + this.name = name; + } + + + + /******************************************************************************* + ** Setter for name + ** + *******************************************************************************/ + public QStepMetaData withName(String name) + { + this.name = name; + return (this); + } + + + + /******************************************************************************* + ** Getter for label + ** + *******************************************************************************/ + public String getLabel() + { + return label; + } + + + + /******************************************************************************* + ** Setter for label + ** + *******************************************************************************/ + public void setLabel(String label) + { + this.label = label; + } + + + + /******************************************************************************* + ** Setter for label + ** + *******************************************************************************/ + public QStepMetaData withLabel(String label) + { + this.label = label; + return (this); + } + + + + /******************************************************************************* + ** Get a list of all of the input fields used by this function + *******************************************************************************/ + @JsonIgnore + public List getInputFields() + { + return (new ArrayList<>()); + } + + + + /******************************************************************************* + ** Get a list of all of the output fields used by this function + *******************************************************************************/ + @JsonIgnore + public List getOutputFields() + { + return (new ArrayList<>()); + } + +} diff --git a/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLExtractFunction.java b/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLExtractFunction.java index cb2e680d..31cb25a8 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLExtractFunction.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLExtractFunction.java @@ -24,9 +24,9 @@ package com.kingsrook.qqq.backend.core.processes.implementations.etl.basic; import com.kingsrook.qqq.backend.core.actions.QueryAction; import com.kingsrook.qqq.backend.core.exceptions.QException; -import com.kingsrook.qqq.backend.core.interfaces.FunctionBody; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionRequest; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionResult; +import com.kingsrook.qqq.backend.core.interfaces.BackendStep; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepRequest; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResult; import com.kingsrook.qqq.backend.core.model.actions.query.QueryRequest; import com.kingsrook.qqq.backend.core.model.actions.query.QueryResult; @@ -34,14 +34,15 @@ import com.kingsrook.qqq.backend.core.model.actions.query.QueryResult; /******************************************************************************* ** Function body for performing the Extract step of a basic ETL process. *******************************************************************************/ -public class BasicETLExtractFunction implements FunctionBody +public class BasicETLExtractFunction implements BackendStep { @Override - public void run(RunFunctionRequest runFunctionRequest, RunFunctionResult runFunctionResult) throws QException + public void run(RunBackendStepRequest runBackendStepRequest, RunBackendStepResult runBackendStepResult) throws QException { - QueryRequest queryRequest = new QueryRequest(runFunctionRequest.getInstance()); - queryRequest.setSession(runFunctionRequest.getSession()); - queryRequest.setTableName(runFunctionRequest.getValueString(BasicETLProcess.FIELD_SOURCE_TABLE)); + QueryRequest queryRequest = new QueryRequest(runBackendStepRequest.getInstance()); + queryRequest.setSession(runBackendStepRequest.getSession()); + queryRequest.setTableName(runBackendStepRequest.getValueString(BasicETLProcess.FIELD_SOURCE_TABLE)); + // queryRequest.setSkip(integerQueryParam(context, "skip")); // queryRequest.setLimit(integerQueryParam(context, "limit")); @@ -54,6 +55,6 @@ public class BasicETLExtractFunction implements FunctionBody QueryAction queryAction = new QueryAction(); QueryResult queryResult = queryAction.execute(queryRequest); - runFunctionResult.setRecords(queryResult.getRecords()); + runBackendStepResult.setRecords(queryResult.getRecords()); } } diff --git a/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLLoadFunction.java b/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLLoadFunction.java index 350db227..ef350b8f 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLLoadFunction.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLLoadFunction.java @@ -26,11 +26,11 @@ import java.util.ArrayList; import java.util.List; import com.kingsrook.qqq.backend.core.actions.InsertAction; import com.kingsrook.qqq.backend.core.exceptions.QException; -import com.kingsrook.qqq.backend.core.interfaces.FunctionBody; +import com.kingsrook.qqq.backend.core.interfaces.BackendStep; import com.kingsrook.qqq.backend.core.model.actions.insert.InsertRequest; import com.kingsrook.qqq.backend.core.model.actions.insert.InsertResult; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionRequest; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionResult; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepRequest; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResult; import com.kingsrook.qqq.backend.core.model.data.QRecord; import com.kingsrook.qqq.backend.core.utils.CollectionUtils; import org.apache.logging.log4j.LogManager; @@ -40,7 +40,7 @@ import org.apache.logging.log4j.Logger; /******************************************************************************* ** Function body for performing the Load step of a basic ETL process. *******************************************************************************/ -public class BasicETLLoadFunction implements FunctionBody +public class BasicETLLoadFunction implements BackendStep { private static final Logger LOG = LogManager.getLogger(BasicETLLoadFunction.class); @@ -50,23 +50,23 @@ public class BasicETLLoadFunction implements FunctionBody ** *******************************************************************************/ @Override - public void run(RunFunctionRequest runFunctionRequest, RunFunctionResult runFunctionResult) throws QException + public void run(RunBackendStepRequest runBackendStepRequest, RunBackendStepResult runBackendStepResult) throws QException { ////////////////////////////////////////////////////// // exit early with no-op if no records made it here // ////////////////////////////////////////////////////// - List inputRecords = runFunctionRequest.getRecords(); + List inputRecords = runBackendStepRequest.getRecords(); LOG.info("Received [" + inputRecords.size() + "] records to load"); if(CollectionUtils.nullSafeIsEmpty(inputRecords)) { - runFunctionResult.addValue(BasicETLProcess.FIELD_RECORD_COUNT, 0); + runBackendStepResult.addValue(BasicETLProcess.FIELD_RECORD_COUNT, 0); return; } ////////////////////////////////////////////////////////////////// // put the destination table name in all records being inserted // ////////////////////////////////////////////////////////////////// - String table = runFunctionRequest.getValueString(BasicETLProcess.FIELD_DESTINATION_TABLE); + String table = runBackendStepRequest.getValueString(BasicETLProcess.FIELD_DESTINATION_TABLE); for(QRecord record : inputRecords) { record.setTableName(table); @@ -82,8 +82,8 @@ public class BasicETLLoadFunction implements FunctionBody for(List page : CollectionUtils.getPages(inputRecords, pageSize)) { LOG.info("Inserting a page of [" + page.size() + "] records. Progress: " + recordsInserted + " loaded out of " + inputRecords.size() + " total"); - InsertRequest insertRequest = new InsertRequest(runFunctionRequest.getInstance()); - insertRequest.setSession(runFunctionRequest.getSession()); + InsertRequest insertRequest = new InsertRequest(runBackendStepRequest.getInstance()); + insertRequest.setSession(runBackendStepRequest.getSession()); insertRequest.setTableName(table); insertRequest.setRecords(page); @@ -93,8 +93,8 @@ public class BasicETLLoadFunction implements FunctionBody recordsInserted += insertResult.getRecords().size(); } - runFunctionResult.setRecords(outputRecords); - runFunctionResult.addValue(BasicETLProcess.FIELD_RECORD_COUNT, recordsInserted); + runBackendStepResult.setRecords(outputRecords); + runBackendStepResult.addValue(BasicETLProcess.FIELD_RECORD_COUNT, recordsInserted); } } diff --git a/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLProcess.java b/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLProcess.java index b245252c..f190da71 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLProcess.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLProcess.java @@ -27,10 +27,11 @@ import com.kingsrook.qqq.backend.core.model.metadata.QCodeType; import com.kingsrook.qqq.backend.core.model.metadata.QCodeUsage; import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData; import com.kingsrook.qqq.backend.core.model.metadata.QFieldType; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMetaData; -import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionOutputMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData; /******************************************************************************* @@ -54,7 +55,7 @@ public class BasicETLProcess *******************************************************************************/ public QProcessMetaData defineProcessMetaData() { - QFunctionMetaData extractFunction = new QFunctionMetaData() + QStepMetaData extractFunction = new QBackendStepMetaData() .withName(FUNCTION_NAME_EXTRACT) .withCode(new QCodeReference() .withName(BasicETLExtractFunction.class.getName()) @@ -63,7 +64,7 @@ public class BasicETLProcess .withInputData(new QFunctionInputMetaData() .addField(new QFieldMetaData(FIELD_SOURCE_TABLE, QFieldType.STRING))); - QFunctionMetaData transformFunction = new QFunctionMetaData() + QStepMetaData transformFunction = new QBackendStepMetaData() .withName(FUNCTION_NAME_TRANSFORM) .withCode(new QCodeReference() .withName(BasicETLTransformFunction.class.getName()) @@ -73,7 +74,7 @@ public class BasicETLProcess .addField(new QFieldMetaData(FIELD_MAPPING_JSON, QFieldType.STRING)) .addField(new QFieldMetaData(FIELD_DESTINATION_TABLE, QFieldType.STRING))); - QFunctionMetaData loadFunction = new QFunctionMetaData() + QStepMetaData loadFunction = new QBackendStepMetaData() .withName(FUNCTION_NAME_LOAD) .withCode(new QCodeReference() .withName(BasicETLLoadFunction.class.getName()) @@ -86,8 +87,8 @@ public class BasicETLProcess return new QProcessMetaData() .withName(PROCESS_NAME) - .addFunction(extractFunction) - .addFunction(transformFunction) - .addFunction(loadFunction); + .addStep(extractFunction) + .addStep(transformFunction) + .addStep(loadFunction); } } diff --git a/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLTransformFunction.java b/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLTransformFunction.java index 4d19d2d3..34c168a0 100644 --- a/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLTransformFunction.java +++ b/src/main/java/com/kingsrook/qqq/backend/core/processes/implementations/etl/basic/BasicETLTransformFunction.java @@ -28,9 +28,9 @@ import java.util.ArrayList; import java.util.List; import com.kingsrook.qqq.backend.core.adapters.JsonToQFieldMappingAdapter; import com.kingsrook.qqq.backend.core.exceptions.QException; -import com.kingsrook.qqq.backend.core.interfaces.FunctionBody; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionRequest; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionResult; +import com.kingsrook.qqq.backend.core.interfaces.BackendStep; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepRequest; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResult; import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.AbstractQFieldMapping; import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.QKeyBasedFieldMapping; import com.kingsrook.qqq.backend.core.model.data.QRecord; @@ -46,7 +46,7 @@ import org.apache.logging.log4j.Logger; /******************************************************************************* ** Function body for performing the Extract step of a basic ETL process. *******************************************************************************/ -public class BasicETLTransformFunction implements FunctionBody +public class BasicETLTransformFunction implements BackendStep { private static final Logger LOG = LogManager.getLogger(BasicETLTransformFunction.class); @@ -56,17 +56,17 @@ public class BasicETLTransformFunction implements FunctionBody ** *******************************************************************************/ @Override - public void run(RunFunctionRequest runFunctionRequest, RunFunctionResult runFunctionResult) throws QException + public void run(RunBackendStepRequest runBackendStepRequest, RunBackendStepResult runBackendStepResult) throws QException { //////////////////////////////////////////////////////////////////////////////////////////// // exit early with no-op if no records made it here, or if we don't have a mapping to use // //////////////////////////////////////////////////////////////////////////////////////////// - if(CollectionUtils.nullSafeIsEmpty(runFunctionRequest.getRecords())) + if(CollectionUtils.nullSafeIsEmpty(runBackendStepRequest.getRecords())) { return; } - String mappingJSON = runFunctionRequest.getValueString(BasicETLProcess.FIELD_MAPPING_JSON); + String mappingJSON = runBackendStepRequest.getValueString(BasicETLProcess.FIELD_MAPPING_JSON); if(!StringUtils.hasContent(mappingJSON)) { return; @@ -81,16 +81,16 @@ public class BasicETLTransformFunction implements FunctionBody throw (new QException("Mapping was not a Key-based mapping type. Was a : " + mapping.getClass().getName())); } - String tableName = runFunctionRequest.getValueString(BasicETLProcess.FIELD_DESTINATION_TABLE); - QTableMetaData table = runFunctionRequest.getInstance().getTable(tableName); - List mappedRecords = applyMapping(runFunctionRequest.getRecords(), table, keyBasedFieldMapping); + String tableName = runBackendStepRequest.getValueString(BasicETLProcess.FIELD_DESTINATION_TABLE); + QTableMetaData table = runBackendStepRequest.getInstance().getTable(tableName); + List mappedRecords = applyMapping(runBackendStepRequest.getRecords(), table, keyBasedFieldMapping); ////////////////////////////////////////////////////////////////////////////////////////////////////// // todo - should this be conditional, e.g., driven by a field, or an opt-in customization function? // ////////////////////////////////////////////////////////////////////////////////////////////////////// removeNonNumericValuesFromMappedRecords(table, mappedRecords); - runFunctionResult.setRecords(mappedRecords); + runBackendStepResult.setRecords(mappedRecords); } diff --git a/src/test/java/com/kingsrook/qqq/backend/core/actions/ProcessMetaDataActionTest.java b/src/test/java/com/kingsrook/qqq/backend/core/actions/ProcessMetaDataActionTest.java new file mode 100644 index 00000000..0fb620ae --- /dev/null +++ b/src/test/java/com/kingsrook/qqq/backend/core/actions/ProcessMetaDataActionTest.java @@ -0,0 +1,78 @@ +/* + * 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; + + +import com.kingsrook.qqq.backend.core.exceptions.QException; +import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException; +import com.kingsrook.qqq.backend.core.model.actions.metadata.process.ProcessMetaDataRequest; +import com.kingsrook.qqq.backend.core.model.actions.metadata.process.ProcessMetaDataResult; +import com.kingsrook.qqq.backend.core.utils.TestUtils; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + + +/******************************************************************************* + ** Unit test for ProcessMetaDataAction + ** + *******************************************************************************/ +class ProcessMetaDataActionTest +{ + + /******************************************************************************* + ** Test basic success case. + ** + *******************************************************************************/ + @Test + public void test() throws QException + { + ProcessMetaDataRequest request = new ProcessMetaDataRequest(TestUtils.defineInstance()); + request.setSession(TestUtils.getMockSession()); + request.setProcessName(TestUtils.PROCESS_NAME_GREET_PEOPLE_INTERACTIVE); + ProcessMetaDataResult result = new ProcessMetaDataAction().execute(request); + assertNotNull(result); + assertNotNull(result.getProcess()); + assertEquals("greetInteractive", result.getProcess().getName()); + assertEquals("Greet Interactive", result.getProcess().getLabel()); + assertEquals(2, result.getProcess().getFrontendSteps().size()); + } + + + + /******************************************************************************* + ** Test exception is thrown for the "not-found" case. + ** + *******************************************************************************/ + @Test + public void test_notFound() + { + assertThrows(QUserFacingException.class, () -> { + ProcessMetaDataRequest request = new ProcessMetaDataRequest(TestUtils.defineInstance()); + request.setSession(TestUtils.getMockSession()); + request.setProcessName("willNotBeFound"); + new ProcessMetaDataAction().execute(request); + }); + } + +} diff --git a/src/test/java/com/kingsrook/qqq/backend/core/actions/RunFunctionTest.java b/src/test/java/com/kingsrook/qqq/backend/core/actions/RunBackendStepActionTest.java similarity index 92% rename from src/test/java/com/kingsrook/qqq/backend/core/actions/RunFunctionTest.java rename to src/test/java/com/kingsrook/qqq/backend/core/actions/RunBackendStepActionTest.java index dead53ea..6fcec55f 100644 --- a/src/test/java/com/kingsrook/qqq/backend/core/actions/RunFunctionTest.java +++ b/src/test/java/com/kingsrook/qqq/backend/core/actions/RunBackendStepActionTest.java @@ -29,8 +29,8 @@ import java.util.List; import java.util.Map; import com.kingsrook.qqq.backend.core.callbacks.QProcessCallback; import com.kingsrook.qqq.backend.core.exceptions.QException; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionRequest; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionResult; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepRequest; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResult; import com.kingsrook.qqq.backend.core.model.actions.query.QQueryFilter; import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData; import com.kingsrook.qqq.backend.core.utils.TestUtils; @@ -44,7 +44,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; /******************************************************************************* ** *******************************************************************************/ -public class RunFunctionTest +public class RunBackendStepActionTest { /******************************************************************************* @@ -53,13 +53,13 @@ public class RunFunctionTest @Test public void test() throws QException { - TestCallback callback = new TestCallback(); - RunFunctionRequest request = new RunFunctionRequest(TestUtils.defineInstance()); + TestCallback callback = new TestCallback(); + RunBackendStepRequest request = new RunBackendStepRequest(TestUtils.defineInstance()); request.setSession(TestUtils.getMockSession()); request.setProcessName("greet"); - request.setFunctionName("prepare"); + request.setStepName("prepare"); request.setCallback(callback); - RunFunctionResult result = new RunFunctionAction().execute(request); + RunBackendStepResult result = new RunBackendStepAction().execute(request); assertNotNull(result); assertNull(result.getError()); assertTrue(result.getRecords().stream().allMatch(r -> r.getValues().containsKey("mockValue")), "records should have a mock value"); diff --git a/src/test/java/com/kingsrook/qqq/backend/core/actions/processes/person/addtopeoplesage/AddAge.java b/src/test/java/com/kingsrook/qqq/backend/core/actions/processes/person/addtopeoplesage/AddAge.java index 5462dd7e..553c9fe5 100644 --- a/src/test/java/com/kingsrook/qqq/backend/core/actions/processes/person/addtopeoplesage/AddAge.java +++ b/src/test/java/com/kingsrook/qqq/backend/core/actions/processes/person/addtopeoplesage/AddAge.java @@ -22,29 +22,29 @@ package com.kingsrook.qqq.backend.core.actions.processes.person.addtopeoplesage; -import com.kingsrook.qqq.backend.core.interfaces.FunctionBody; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionRequest; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionResult; +import com.kingsrook.qqq.backend.core.interfaces.BackendStep; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepRequest; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResult; import com.kingsrook.qqq.backend.core.model.data.QRecord; /******************************************************************************* ** *******************************************************************************/ -public class AddAge implements FunctionBody +public class AddAge implements BackendStep { @Override - public void run(RunFunctionRequest runFunctionRequest, RunFunctionResult runFunctionResult) + public void run(RunBackendStepRequest runBackendStepRequest, RunBackendStepResult runBackendStepResult) { int totalYearsAdded = 0; - Integer yearsToAdd = runFunctionRequest.getValueInteger("yearsToAdd"); - for(QRecord record : runFunctionRequest.getRecords()) + Integer yearsToAdd = runBackendStepRequest.getValueInteger("yearsToAdd"); + for(QRecord record : runBackendStepRequest.getRecords()) { Integer age = record.getValueInteger("age"); age += yearsToAdd; totalYearsAdded += yearsToAdd; record.setValue("age", age); } - runFunctionResult.addValue("totalYearsAdded", totalYearsAdded); + runBackendStepResult.addValue("totalYearsAdded", totalYearsAdded); } } diff --git a/src/test/java/com/kingsrook/qqq/backend/core/actions/processes/person/addtopeoplesage/GetAgeStatistics.java b/src/test/java/com/kingsrook/qqq/backend/core/actions/processes/person/addtopeoplesage/GetAgeStatistics.java index c06d7150..edc6da4b 100644 --- a/src/test/java/com/kingsrook/qqq/backend/core/actions/processes/person/addtopeoplesage/GetAgeStatistics.java +++ b/src/test/java/com/kingsrook/qqq/backend/core/actions/processes/person/addtopeoplesage/GetAgeStatistics.java @@ -24,24 +24,24 @@ package com.kingsrook.qqq.backend.core.actions.processes.person.addtopeoplesage; import java.time.LocalDate; import java.time.Period; -import com.kingsrook.qqq.backend.core.interfaces.FunctionBody; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionRequest; -import com.kingsrook.qqq.backend.core.model.actions.processes.RunFunctionResult; +import com.kingsrook.qqq.backend.core.interfaces.BackendStep; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepRequest; +import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepResult; import com.kingsrook.qqq.backend.core.model.data.QRecord; /******************************************************************************* ** *******************************************************************************/ -public class GetAgeStatistics implements FunctionBody +public class GetAgeStatistics implements BackendStep { @Override - public void run(RunFunctionRequest runFunctionRequest, RunFunctionResult runFunctionResult) + public void run(RunBackendStepRequest runBackendStepRequest, RunBackendStepResult runBackendStepResult) { Integer min = null; Integer max = null; LocalDate now = LocalDate.now(); - for(QRecord record : runFunctionRequest.getRecords()) + for(QRecord record : runBackendStepRequest.getRecords()) { LocalDate birthDate = record.getValueDate("birthDate"); Period until = birthDate.until(now); @@ -52,7 +52,7 @@ public class GetAgeStatistics implements FunctionBody max = (max == null || age > max) ? age : max; } - runFunctionResult.addValue("minAge", min); - runFunctionResult.addValue("maxAge", max); + runBackendStepResult.addValue("minAge", min); + runBackendStepResult.addValue("maxAge", max); } } diff --git a/src/test/java/com/kingsrook/qqq/backend/core/utils/TestUtils.java b/src/test/java/com/kingsrook/qqq/backend/core/utils/TestUtils.java index e8a70e60..b7de6689 100644 --- a/src/test/java/com/kingsrook/qqq/backend/core/utils/TestUtils.java +++ b/src/test/java/com/kingsrook/qqq/backend/core/utils/TestUtils.java @@ -23,7 +23,8 @@ package com.kingsrook.qqq.backend.core.utils; import java.util.List; -import com.kingsrook.qqq.backend.core.interfaces.mock.MockFunctionBody; +import com.kingsrook.qqq.backend.core.adapters.QInstanceAdapter; +import com.kingsrook.qqq.backend.core.interfaces.mock.MockBackendStep; import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationMetaData; import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData; import com.kingsrook.qqq.backend.core.model.metadata.QCodeReference; @@ -35,13 +36,12 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource; import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSourceType; +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.QFunctionInputMetaData; -import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionOutputMetaData; -import com.kingsrook.qqq.backend.core.model.metadata.processes.QOutputView; import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; import com.kingsrook.qqq.backend.core.model.metadata.processes.QRecordListMetaData; -import com.kingsrook.qqq.backend.core.model.metadata.processes.QRecordListView; import com.kingsrook.qqq.backend.core.model.session.QSession; import com.kingsrook.qqq.backend.core.modules.mock.MockAuthenticationModule; import com.kingsrook.qqq.backend.core.processes.implementations.etl.basic.BasicETLProcess; @@ -54,6 +54,8 @@ import com.kingsrook.qqq.backend.core.processes.implementations.etl.basic.BasicE public class TestUtils { public static String DEFAULT_BACKEND_NAME = "default"; + public static String PROCESS_NAME_GREET_PEOPLE = "greet"; + public static String PROCESS_NAME_GREET_PEOPLE_INTERACTIVE = "greetInteractive"; @@ -71,8 +73,12 @@ public class TestUtils qInstance.addTable(defineTableIdAndNameOnly()); qInstance.addPossibleValueSource(defineStatesPossibleValueSource()); qInstance.addProcess(defineProcessGreetPeople()); + qInstance.addProcess(defineProcessGreetPeopleInteractive()); qInstance.addProcess(defineProcessAddToPeoplesAge()); qInstance.addProcess(new BasicETLProcess().defineProcessMetaData()); + + System.out.println(new QInstanceAdapter().qInstanceToJson(qInstance)); + return (qInstance); } @@ -176,12 +182,12 @@ public class TestUtils private static QProcessMetaData defineProcessGreetPeople() { return new QProcessMetaData() - .withName("greet") + .withName(PROCESS_NAME_GREET_PEOPLE) .withTableName("person") - .addFunction(new QFunctionMetaData() + .addStep(new QBackendStepMetaData() .withName("prepare") .withCode(new QCodeReference() - .withName(MockFunctionBody.class.getName()) + .withName(MockBackendStep.class.getName()) .withCodeType(QCodeType.JAVA) .withCodeUsage(QCodeUsage.FUNCTION)) // todo - needed, or implied in this context? .withInputData(new QFunctionInputMetaData() @@ -196,9 +202,49 @@ public class TestUtils .addField(new QFieldMetaData("fullGreeting", QFieldType.STRING)) ) .withFieldList(List.of(new QFieldMetaData("outputMessage", QFieldType.STRING)))) - .withOutputView(new QOutputView() - .withMessageField("outputMessage") - .withRecordListView(new QRecordListView().withFieldNames(List.of("id", "firstName", "lastName", "fullGreeting")))) + ); + } + + + + /******************************************************************************* + ** Define an interactive version of the 'greet people' process + *******************************************************************************/ + private static QProcessMetaData defineProcessGreetPeopleInteractive() + { + return new QProcessMetaData() + .withName(PROCESS_NAME_GREET_PEOPLE_INTERACTIVE) + .withTableName("person") + + .addStep(new QFrontendStepMetaData() + .withName("setup") + .withFormField(new QFieldMetaData("greetingPrefix", QFieldType.STRING)) + .withFormField(new QFieldMetaData("greetingSuffix", QFieldType.STRING)) + ) + + .addStep(new QBackendStepMetaData() + .withName("doWork") + .withCode(new QCodeReference() + .withName(MockBackendStep.class.getName()) + .withCodeType(QCodeType.JAVA) + .withCodeUsage(QCodeUsage.FUNCTION)) // todo - needed, or implied in this context? + .withInputData(new QFunctionInputMetaData() + .withRecordListMetaData(new QRecordListMetaData().withTableName("person")) + .withFieldList(List.of( + new QFieldMetaData("greetingPrefix", QFieldType.STRING), + new QFieldMetaData("greetingSuffix", QFieldType.STRING) + ))) + .withOutputMetaData(new QFunctionOutputMetaData() + .withRecordListMetaData(new QRecordListMetaData() + .withTableName("person") + .addField(new QFieldMetaData("fullGreeting", QFieldType.STRING)) + ) + .withFieldList(List.of(new QFieldMetaData("outputMessage", QFieldType.STRING)))) + ) + + .addStep(new QFrontendStepMetaData() + .withName("results") + .withFormField(new QFieldMetaData("outputMessage", QFieldType.STRING)) ); } @@ -217,7 +263,7 @@ public class TestUtils return new QProcessMetaData() .withName("addToPeoplesAge") .withTableName("person") - .addFunction(new QFunctionMetaData() + .addStep(new QBackendStepMetaData() .withName("getAgeStatistics") .withCode(new QCodeReference() .withName("com.kingsrook.qqq.backend.core.actions.processes.person.addtopeoplesage.GetAgeStatistics") @@ -231,10 +277,8 @@ public class TestUtils .addField(new QFieldMetaData("age", QFieldType.INTEGER))) .withFieldList(List.of( new QFieldMetaData("minAge", QFieldType.INTEGER), - new QFieldMetaData("maxAge", QFieldType.INTEGER)))) - .withOutputView(new QOutputView() - .withMessageField("outputMessage"))) // todo - wut? - .addFunction(new QFunctionMetaData() + new QFieldMetaData("maxAge", QFieldType.INTEGER))))) + .addStep(new QBackendStepMetaData() .withName("addAge") .withCode(new QCodeReference() .withName("com.kingsrook.qqq.backend.core.actions.processes.person.addtopeoplesage.AddAge")