mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
Cleanup from code review
This commit is contained in:
@ -22,6 +22,7 @@
|
|||||||
package com.kingsrook.qqq.backend.core.actions.dashboard;
|
package com.kingsrook.qqq.backend.core.actions.dashboard;
|
||||||
|
|
||||||
|
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
|
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput;
|
||||||
@ -51,6 +52,8 @@ public class QuickSightChartRenderer extends AbstractWidgetRenderer
|
|||||||
@Override
|
@Override
|
||||||
public RenderWidgetOutput render(RenderWidgetInput input) throws QException
|
public RenderWidgetOutput render(RenderWidgetInput input) throws QException
|
||||||
{
|
{
|
||||||
|
ActionHelper.validateSession(input);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
QuickSightChartMetaData quickSightMetaData = (QuickSightChartMetaData) input.getWidgetMetaData();
|
QuickSightChartMetaData quickSightMetaData = (QuickSightChartMetaData) input.getWidgetMetaData();
|
||||||
|
@ -30,6 +30,7 @@ import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
|||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput;
|
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface;
|
import com.kingsrook.qqq.backend.core.model.metadata.dashboard.QWidgetMetaDataInterface;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.frontend.AppTreeNode;
|
import com.kingsrook.qqq.backend.core.model.metadata.frontend.AppTreeNode;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendAppMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendAppMetaData;
|
||||||
@ -69,8 +70,10 @@ public class MetaDataAction
|
|||||||
Map<String, QFrontendTableMetaData> tables = new LinkedHashMap<>();
|
Map<String, QFrontendTableMetaData> tables = new LinkedHashMap<>();
|
||||||
for(Map.Entry<String, QTableMetaData> entry : metaDataInput.getInstance().getTables().entrySet())
|
for(Map.Entry<String, QTableMetaData> entry : metaDataInput.getInstance().getTables().entrySet())
|
||||||
{
|
{
|
||||||
tables.put(entry.getKey(), new QFrontendTableMetaData(entry.getValue(), false));
|
String tableName = entry.getKey();
|
||||||
treeNodes.put(entry.getKey(), new AppTreeNode(entry.getValue()));
|
QBackendMetaData backendForTable = metaDataInput.getInstance().getBackendForTable(tableName);
|
||||||
|
tables.put(tableName, new QFrontendTableMetaData(backendForTable, entry.getValue(), false));
|
||||||
|
treeNodes.put(tableName, new AppTreeNode(entry.getValue()));
|
||||||
}
|
}
|
||||||
metaDataOutput.setTables(tables);
|
metaDataOutput.setTables(tables);
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ import com.kingsrook.qqq.backend.core.exceptions.QException;
|
|||||||
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataInput;
|
import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendTableMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
|
|
||||||
@ -52,7 +53,8 @@ public class TableMetaDataAction
|
|||||||
{
|
{
|
||||||
throw (new QNotFoundException("Table [" + tableMetaDataInput.getTableName() + "] was not found."));
|
throw (new QNotFoundException("Table [" + tableMetaDataInput.getTableName() + "] was not found."));
|
||||||
}
|
}
|
||||||
tableMetaDataOutput.setTable(new QFrontendTableMetaData(table, true));
|
QBackendMetaData backendForTable = tableMetaDataInput.getInstance().getBackendForTable(table.getName());
|
||||||
|
tableMetaDataOutput.setTable(new QFrontendTableMetaData(backendForTable, table, true));
|
||||||
|
|
||||||
// todo post-customization - can do whatever w/ the result if you want
|
// todo post-customization - can do whatever w/ the result if you want
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@ package com.kingsrook.qqq.backend.core.actions.scripts;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.Log4jCodeExecutionLogger;
|
import com.kingsrook.qqq.backend.core.actions.scripts.logging.Log4jCodeExecutionLogger;
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.QCodeExecutionLoggerInterface;
|
import com.kingsrook.qqq.backend.core.actions.scripts.logging.QCodeExecutionLoggerInterface;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QCodeException;
|
import com.kingsrook.qqq.backend.core.exceptions.QCodeException;
|
||||||
@ -33,7 +35,17 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
** Action to execute user/runtime defined code.
|
||||||
**
|
**
|
||||||
|
** This action is designed to support code in multiple languages, by using
|
||||||
|
** executors, e.g., provided by additional runtime qqq dependencies. Initially
|
||||||
|
** we are building qqq-language-support-javascript.
|
||||||
|
**
|
||||||
|
** We also have a Java executor, to provide at least a little bit of testability
|
||||||
|
** within qqq-backend-core. This executor is a candidate to be replaced in the
|
||||||
|
** future with something that would do actual dynamic java (whether that's compiled
|
||||||
|
** at runtime, or loaded from a plugin jar at runtime). In other words, the java
|
||||||
|
** executor in place today is just meant to be a placeholder.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class ExecuteCodeAction
|
public class ExecuteCodeAction
|
||||||
{
|
{
|
||||||
@ -65,7 +77,20 @@ public class ExecuteCodeAction
|
|||||||
Class<? extends QCodeExecutor> executorClass = (Class<? extends QCodeExecutor>) Class.forName(languageExecutor);
|
Class<? extends QCodeExecutor> executorClass = (Class<? extends QCodeExecutor>) Class.forName(languageExecutor);
|
||||||
QCodeExecutor qCodeExecutor = executorClass.getConstructor().newInstance();
|
QCodeExecutor qCodeExecutor = executorClass.getConstructor().newInstance();
|
||||||
|
|
||||||
Serializable codeOutput = qCodeExecutor.execute(codeReference, input.getContext(), executionLogger);
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// merge all of the input context, plus the input... input - into a context for the code executor //
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Map<String, Serializable> context = new HashMap<>();
|
||||||
|
if(input.getContext() != null)
|
||||||
|
{
|
||||||
|
context.putAll(input.getContext());
|
||||||
|
}
|
||||||
|
if(input.getInput() != null)
|
||||||
|
{
|
||||||
|
context.putAll(input.getInput());
|
||||||
|
}
|
||||||
|
|
||||||
|
Serializable codeOutput = qCodeExecutor.execute(codeReference, context, executionLogger);
|
||||||
output.setOutput(codeOutput);
|
output.setOutput(codeOutput);
|
||||||
executionLogger.acceptExecutionEnd(codeOutput);
|
executionLogger.acceptExecutionEnd(codeOutput);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,8 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Interface to be implemented by language-specific code executors, e.g., in
|
||||||
|
** qqq-language-support-${languageName} maven modules.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public interface QCodeExecutor
|
public interface QCodeExecutor
|
||||||
{
|
{
|
||||||
@ -38,6 +39,6 @@ public interface QCodeExecutor
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
Serializable execute(QCodeReference codeReference, Map<String, Serializable> context, QCodeExecutionLoggerInterface executionLogger) throws QCodeException;
|
Serializable execute(QCodeReference codeReference, Map<String, Serializable> inputContext, QCodeExecutionLoggerInterface executionLogger) throws QCodeException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Java
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class QJavaExecutor implements QCodeExecutor
|
public class QJavaExecutor implements QCodeExecutor
|
||||||
{
|
{
|
||||||
@ -42,9 +42,9 @@ public class QJavaExecutor implements QCodeExecutor
|
|||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@Override
|
@Override
|
||||||
public Serializable execute(QCodeReference codeReference, Map<String, Serializable> input, QCodeExecutionLoggerInterface executionLogger) throws QCodeException
|
public Serializable execute(QCodeReference codeReference, Map<String, Serializable> inputContext, QCodeExecutionLoggerInterface executionLogger) throws QCodeException
|
||||||
{
|
{
|
||||||
Map<String, Object> context = new HashMap<>(input);
|
Map<String, Object> context = new HashMap<>(inputContext);
|
||||||
if(!context.containsKey("logger"))
|
if(!context.containsKey("logger"))
|
||||||
{
|
{
|
||||||
context.put("logger", executionLogger);
|
context.put("logger", executionLogger);
|
||||||
|
@ -24,9 +24,11 @@ package com.kingsrook.qqq.backend.core.actions.scripts;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.HeaderAndDetailTableCodeExecutionLogger;
|
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.scripts.logging.StoreScriptLogAndScriptLogLineExecutionLogger;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.RunAssociatedScriptInput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.RunAssociatedScriptInput;
|
||||||
@ -50,15 +52,34 @@ public class RunAssociatedScriptAction
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public void run(RunAssociatedScriptInput input, RunAssociatedScriptOutput output) throws QException
|
public void run(RunAssociatedScriptInput input, RunAssociatedScriptOutput output) throws QException
|
||||||
{
|
{
|
||||||
|
ActionHelper.validateSession(input);
|
||||||
|
|
||||||
Serializable scriptId = getScriptId(input);
|
Serializable scriptId = getScriptId(input);
|
||||||
|
if(scriptId == null)
|
||||||
|
{
|
||||||
|
throw (new QNotFoundException("The input record [" + input.getCodeReference().getRecordTable() + "][" + input.getCodeReference().getRecordPrimaryKey()
|
||||||
|
+ "] does not have a script specified for [" + input.getCodeReference().getFieldName() + "]"));
|
||||||
|
}
|
||||||
|
|
||||||
Script script = getScript(input, scriptId);
|
Script script = getScript(input, scriptId);
|
||||||
|
if(script.getCurrentScriptRevisionId() == null)
|
||||||
|
{
|
||||||
|
throw (new QNotFoundException("The script for record [" + input.getCodeReference().getRecordTable() + "][" + input.getCodeReference().getRecordPrimaryKey()
|
||||||
|
+ "] (scriptId=" + scriptId + ") does not have a current version."));
|
||||||
|
}
|
||||||
|
|
||||||
ScriptRevision scriptRevision = getCurrentScriptRevision(input, script.getCurrentScriptRevisionId());
|
ScriptRevision scriptRevision = getCurrentScriptRevision(input, script.getCurrentScriptRevisionId());
|
||||||
|
|
||||||
ExecuteCodeInput executeCodeInput = new ExecuteCodeInput(input.getInstance());
|
ExecuteCodeInput executeCodeInput = new ExecuteCodeInput(input.getInstance());
|
||||||
executeCodeInput.setSession(input.getSession());
|
executeCodeInput.setSession(input.getSession());
|
||||||
executeCodeInput.setContext(new HashMap<>(input.getInputValues()));
|
executeCodeInput.setInput(new HashMap<>(input.getInputValues()));
|
||||||
executeCodeInput.setCodeReference(new QCodeReference().withInlineCode(scriptRevision.getContents()).withCodeType(QCodeType.JAVA_SCRIPT));
|
executeCodeInput.setContext(new HashMap<>());
|
||||||
executeCodeInput.setExecutionLogger(new HeaderAndDetailTableCodeExecutionLogger(scriptRevision.getScriptId(), scriptRevision.getId()));
|
if(input.getOutputObject() != null)
|
||||||
|
{
|
||||||
|
executeCodeInput.getContext().put("output", input.getOutputObject());
|
||||||
|
}
|
||||||
|
executeCodeInput.setCodeReference(new QCodeReference().withInlineCode(scriptRevision.getContents()).withCodeType(QCodeType.JAVA_SCRIPT)); // todo - code type as attribute of script!!
|
||||||
|
executeCodeInput.setExecutionLogger(new StoreScriptLogAndScriptLogLineExecutionLogger(scriptRevision.getScriptId(), scriptRevision.getId()));
|
||||||
ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput();
|
ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput();
|
||||||
new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput);
|
new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput);
|
||||||
|
|
||||||
@ -77,6 +98,12 @@ public class RunAssociatedScriptAction
|
|||||||
getInput.setTableName("scriptRevision");
|
getInput.setTableName("scriptRevision");
|
||||||
getInput.setPrimaryKey(scriptRevisionId);
|
getInput.setPrimaryKey(scriptRevisionId);
|
||||||
GetOutput getOutput = new GetAction().execute(getInput);
|
GetOutput getOutput = new GetAction().execute(getInput);
|
||||||
|
if(getOutput.getRecord() == null)
|
||||||
|
{
|
||||||
|
throw (new QNotFoundException("The current revision of the script for record [" + input.getCodeReference().getRecordTable() + "][" + input.getCodeReference().getRecordPrimaryKey() + "]["
|
||||||
|
+ input.getCodeReference().getFieldName() + "] (scriptRevisionId=" + scriptRevisionId + ") was not found."));
|
||||||
|
}
|
||||||
|
|
||||||
return (new ScriptRevision(getOutput.getRecord()));
|
return (new ScriptRevision(getOutput.getRecord()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,6 +119,13 @@ public class RunAssociatedScriptAction
|
|||||||
getInput.setTableName("script");
|
getInput.setTableName("script");
|
||||||
getInput.setPrimaryKey(scriptId);
|
getInput.setPrimaryKey(scriptId);
|
||||||
GetOutput getOutput = new GetAction().execute(getInput);
|
GetOutput getOutput = new GetAction().execute(getInput);
|
||||||
|
|
||||||
|
if(getOutput.getRecord() == null)
|
||||||
|
{
|
||||||
|
throw (new QNotFoundException("The script for record [" + input.getCodeReference().getRecordTable() + "][" + input.getCodeReference().getRecordPrimaryKey() + "]["
|
||||||
|
+ input.getCodeReference().getFieldName() + "] (script id=" + scriptId + ") was not found."));
|
||||||
|
}
|
||||||
|
|
||||||
return (new Script(getOutput.getRecord()));
|
return (new Script(getOutput.getRecord()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,6 +141,11 @@ public class RunAssociatedScriptAction
|
|||||||
getInput.setTableName(input.getCodeReference().getRecordTable());
|
getInput.setTableName(input.getCodeReference().getRecordTable());
|
||||||
getInput.setPrimaryKey(input.getCodeReference().getRecordPrimaryKey());
|
getInput.setPrimaryKey(input.getCodeReference().getRecordPrimaryKey());
|
||||||
GetOutput getOutput = new GetAction().execute(getInput);
|
GetOutput getOutput = new GetAction().execute(getInput);
|
||||||
|
if(getOutput.getRecord() == null)
|
||||||
|
{
|
||||||
|
throw (new QNotFoundException("The requested record [" + input.getCodeReference().getRecordTable() + "][" + input.getCodeReference().getRecordPrimaryKey() + "] was not found."));
|
||||||
|
}
|
||||||
|
|
||||||
return (getOutput.getRecord().getValue(input.getCodeReference().getFieldName()));
|
return (getOutput.getRecord().getValue(input.getCodeReference().getFieldName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ package com.kingsrook.qqq.backend.core.actions.scripts;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||||
@ -50,6 +51,13 @@ import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
** Action to store a new version of a script, associated with a record.
|
||||||
|
**
|
||||||
|
** If there's never been a script assigned to the record (for the specified field),
|
||||||
|
** then a new Script record is first inserted.
|
||||||
|
**
|
||||||
|
** The script referenced by the record is always updated to point at the new
|
||||||
|
** scriptRevision record that is inserted.
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class StoreAssociatedScriptAction
|
public class StoreAssociatedScriptAction
|
||||||
@ -60,6 +68,8 @@ public class StoreAssociatedScriptAction
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public void run(StoreAssociatedScriptInput input, StoreAssociatedScriptOutput output) throws QException
|
public void run(StoreAssociatedScriptInput input, StoreAssociatedScriptOutput output) throws QException
|
||||||
{
|
{
|
||||||
|
ActionHelper.validateSession(input);
|
||||||
|
|
||||||
QTableMetaData table = input.getTable();
|
QTableMetaData table = input.getTable();
|
||||||
Optional<AssociatedScript> optAssociatedScript = table.getAssociatedScripts().stream().filter(as -> as.getFieldName().equals(input.getFieldName())).findFirst();
|
Optional<AssociatedScript> optAssociatedScript = table.getAssociatedScripts().stream().filter(as -> as.getFieldName().equals(input.getFieldName())).findFirst();
|
||||||
if(optAssociatedScript.isEmpty())
|
if(optAssociatedScript.isEmpty())
|
||||||
@ -77,6 +87,7 @@ public class StoreAssociatedScriptAction
|
|||||||
getInput.setSession(input.getSession());
|
getInput.setSession(input.getSession());
|
||||||
getInput.setTableName(input.getTableName());
|
getInput.setTableName(input.getTableName());
|
||||||
getInput.setPrimaryKey(input.getRecordPrimaryKey());
|
getInput.setPrimaryKey(input.getRecordPrimaryKey());
|
||||||
|
getInput.setShouldGenerateDisplayValues(true);
|
||||||
GetOutput getOutput = new GetAction().execute(getInput);
|
GetOutput getOutput = new GetAction().execute(getInput);
|
||||||
associatedRecord = getOutput.getRecord();
|
associatedRecord = getOutput.getRecord();
|
||||||
}
|
}
|
||||||
@ -100,8 +111,13 @@ public class StoreAssociatedScriptAction
|
|||||||
getInput.setSession(input.getSession());
|
getInput.setSession(input.getSession());
|
||||||
getInput.setTableName("scriptType");
|
getInput.setTableName("scriptType");
|
||||||
getInput.setPrimaryKey(associatedScript.getScriptTypeId());
|
getInput.setPrimaryKey(associatedScript.getScriptTypeId());
|
||||||
|
getInput.setShouldGenerateDisplayValues(true);
|
||||||
GetOutput getOutput = new GetAction().execute(getInput);
|
GetOutput getOutput = new GetAction().execute(getInput);
|
||||||
QRecord scriptType = getOutput.getRecord();
|
QRecord scriptType = getOutput.getRecord();
|
||||||
|
if(scriptType == null)
|
||||||
|
{
|
||||||
|
throw (new QException("Script type [" + associatedScript.getScriptTypeId() + "] was not found."));
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////
|
/////////////////////////
|
||||||
// insert a new script //
|
// insert a new script //
|
||||||
|
@ -22,14 +22,20 @@
|
|||||||
package com.kingsrook.qqq.backend.core.actions.scripts;
|
package com.kingsrook.qqq.backend.core.actions.scripts;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.scripts.logging.BuildScriptLogAndScriptLogLineExecutionLogger;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptInput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Class for running a test of a script - e.g., maybe before it is saved.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class TestScriptAction
|
public class TestScriptAction
|
||||||
{
|
{
|
||||||
@ -40,5 +46,20 @@ public class TestScriptAction
|
|||||||
public void run(TestScriptInput input, TestScriptOutput output) throws QException
|
public void run(TestScriptInput input, TestScriptOutput output) throws QException
|
||||||
{
|
{
|
||||||
QTableMetaData table = input.getTable();
|
QTableMetaData table = input.getTable();
|
||||||
|
|
||||||
|
ExecuteCodeInput executeCodeInput = new ExecuteCodeInput(input.getInstance());
|
||||||
|
executeCodeInput.setSession(input.getSession());
|
||||||
|
executeCodeInput.setInput(new HashMap<>(input.getInputValues()));
|
||||||
|
executeCodeInput.setContext(new HashMap<>());
|
||||||
|
// todo! if(input.getOutputObject() != null)
|
||||||
|
// todo! {
|
||||||
|
// todo! executeCodeInput.getContext().put("output", input.getOutputObject());
|
||||||
|
// todo! }
|
||||||
|
executeCodeInput.setCodeReference(new QCodeReference().withInlineCode(input.getCode()).withCodeType(QCodeType.JAVA_SCRIPT)); // todo - code type as attribute of script!!
|
||||||
|
executeCodeInput.setExecutionLogger(new BuildScriptLogAndScriptLogLineExecutionLogger());
|
||||||
|
ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput();
|
||||||
|
new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput);
|
||||||
|
|
||||||
|
// todo! output.setOutput(executeCodeOutput.getOutput());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,30 +27,26 @@ import java.time.Instant;
|
|||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
|
||||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Implementation of a code execution logger that logs into a header and child
|
** Implementation of a code execution logger that builds a scriptLog and 0 or more
|
||||||
** table
|
** scriptLogLine records - but doesn't insert them. e.g., useful for testing
|
||||||
|
** (both in junit, and for users in-app).
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class HeaderAndDetailTableCodeExecutionLogger implements QCodeExecutionLoggerInterface
|
public class BuildScriptLogAndScriptLogLineExecutionLogger implements QCodeExecutionLoggerInterface
|
||||||
{
|
{
|
||||||
private static final Logger LOG = LogManager.getLogger(HeaderAndDetailTableCodeExecutionLogger.class);
|
private static final Logger LOG = LogManager.getLogger(BuildScriptLogAndScriptLogLineExecutionLogger.class);
|
||||||
|
|
||||||
private QRecord header;
|
private QRecord scriptLog;
|
||||||
private List<QRecord> children = new ArrayList<>();
|
private List<QRecord> scriptLogLines = new ArrayList<>();
|
||||||
private ExecuteCodeInput executeCodeInput;
|
protected ExecuteCodeInput executeCodeInput;
|
||||||
|
|
||||||
private Serializable scriptId;
|
private Serializable scriptId;
|
||||||
private Serializable scriptRevisionId;
|
private Serializable scriptRevisionId;
|
||||||
@ -61,7 +57,17 @@ public class HeaderAndDetailTableCodeExecutionLogger implements QCodeExecutionLo
|
|||||||
** Constructor
|
** Constructor
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public HeaderAndDetailTableCodeExecutionLogger(Serializable scriptId, Serializable scriptRevisionId)
|
public BuildScriptLogAndScriptLogLineExecutionLogger()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Constructor
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public BuildScriptLogAndScriptLogLineExecutionLogger(Serializable scriptId, Serializable scriptRevisionId)
|
||||||
{
|
{
|
||||||
this.scriptId = scriptId;
|
this.scriptId = scriptId;
|
||||||
this.scriptRevisionId = scriptRevisionId;
|
this.scriptRevisionId = scriptRevisionId;
|
||||||
@ -78,7 +84,7 @@ public class HeaderAndDetailTableCodeExecutionLogger implements QCodeExecutionLo
|
|||||||
.withValue("scriptId", scriptId)
|
.withValue("scriptId", scriptId)
|
||||||
.withValue("scriptRevisionId", scriptRevisionId)
|
.withValue("scriptRevisionId", scriptRevisionId)
|
||||||
.withValue("startTimestamp", Instant.now())
|
.withValue("startTimestamp", Instant.now())
|
||||||
.withValue("input", truncate(executeCodeInput.getContext().toString())));
|
.withValue("input", truncate(executeCodeInput.getInput())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -89,7 +95,7 @@ public class HeaderAndDetailTableCodeExecutionLogger implements QCodeExecutionLo
|
|||||||
protected QRecord buildDetailLogRecord(String logLine)
|
protected QRecord buildDetailLogRecord(String logLine)
|
||||||
{
|
{
|
||||||
return (new QRecord()
|
return (new QRecord()
|
||||||
.withValue("scriptLogId", header.getValue("id"))
|
.withValue("scriptLogId", scriptLog.getValue("id"))
|
||||||
.withValue("timestamp", Instant.now())
|
.withValue("timestamp", Instant.now())
|
||||||
.withValue("text", truncate(logLine)));
|
.withValue("text", truncate(logLine)));
|
||||||
}
|
}
|
||||||
@ -99,9 +105,9 @@ public class HeaderAndDetailTableCodeExecutionLogger implements QCodeExecutionLo
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private String truncate(String logLine)
|
private String truncate(Object o)
|
||||||
{
|
{
|
||||||
return StringUtils.safeTruncate(logLine, 1000, "...");
|
return StringUtils.safeTruncate(ValueUtils.getValueAsString(o), 1000, "...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -109,22 +115,22 @@ public class HeaderAndDetailTableCodeExecutionLogger implements QCodeExecutionLo
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private void updateHeaderAtEnd(Serializable output, Exception exception)
|
protected void updateHeaderAtEnd(Serializable output, Exception exception)
|
||||||
{
|
{
|
||||||
Instant startTimestamp = (Instant) header.getValue("startTimestamp");
|
Instant startTimestamp = (Instant) scriptLog.getValue("startTimestamp");
|
||||||
Instant endTimestamp = Instant.now();
|
Instant endTimestamp = Instant.now();
|
||||||
header.setValue("endTimestamp", endTimestamp);
|
scriptLog.setValue("endTimestamp", endTimestamp);
|
||||||
header.setValue("runTimeMillis", startTimestamp.until(endTimestamp, ChronoUnit.MILLIS));
|
scriptLog.setValue("runTimeMillis", startTimestamp.until(endTimestamp, ChronoUnit.MILLIS));
|
||||||
|
|
||||||
if(exception != null)
|
if(exception != null)
|
||||||
{
|
{
|
||||||
header.setValue("hadError", true);
|
scriptLog.setValue("hadError", true);
|
||||||
header.setValue("error", exception.getMessage());
|
scriptLog.setValue("error", exception.getMessage());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
header.setValue("hadError", false);
|
scriptLog.setValue("hadError", false);
|
||||||
header.setValue("output", truncate(String.valueOf(output)));
|
scriptLog.setValue("output", truncate(output));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,14 +145,7 @@ public class HeaderAndDetailTableCodeExecutionLogger implements QCodeExecutionLo
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.executeCodeInput = executeCodeInput;
|
this.executeCodeInput = executeCodeInput;
|
||||||
QRecord scriptLog = buildHeaderRecord(executeCodeInput);
|
this.scriptLog = buildHeaderRecord(executeCodeInput);
|
||||||
|
|
||||||
InsertInput insertInput = new InsertInput(executeCodeInput.getInstance());
|
|
||||||
insertInput.setSession(executeCodeInput.getSession());
|
|
||||||
insertInput.setTableName("scriptLog");
|
|
||||||
insertInput.setRecords(List.of(scriptLog));
|
|
||||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
|
||||||
this.header = insertOutput.getRecords().get(0);
|
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
@ -162,7 +161,7 @@ public class HeaderAndDetailTableCodeExecutionLogger implements QCodeExecutionLo
|
|||||||
@Override
|
@Override
|
||||||
public void acceptLogLine(String logLine)
|
public void acceptLogLine(String logLine)
|
||||||
{
|
{
|
||||||
children.add(buildDetailLogRecord(logLine));
|
scriptLogLines.add(buildDetailLogRecord(logLine));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -173,7 +172,7 @@ public class HeaderAndDetailTableCodeExecutionLogger implements QCodeExecutionLo
|
|||||||
@Override
|
@Override
|
||||||
public void acceptException(Exception exception)
|
public void acceptException(Exception exception)
|
||||||
{
|
{
|
||||||
store(null, exception);
|
updateHeaderAtEnd(null, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -184,38 +183,39 @@ public class HeaderAndDetailTableCodeExecutionLogger implements QCodeExecutionLo
|
|||||||
@Override
|
@Override
|
||||||
public void acceptExecutionEnd(Serializable output)
|
public void acceptExecutionEnd(Serializable output)
|
||||||
{
|
{
|
||||||
store(output, null);
|
updateHeaderAtEnd(output, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
** Getter for scriptLog
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private void store(Serializable output, Exception exception)
|
public QRecord getScriptLog()
|
||||||
{
|
{
|
||||||
try
|
return scriptLog;
|
||||||
{
|
|
||||||
updateHeaderAtEnd(output, exception);
|
|
||||||
UpdateInput updateInput = new UpdateInput(executeCodeInput.getInstance());
|
|
||||||
updateInput.setSession(executeCodeInput.getSession());
|
|
||||||
updateInput.setTableName("scriptLog");
|
|
||||||
updateInput.setRecords(List.of(header));
|
|
||||||
new UpdateAction().execute(updateInput);
|
|
||||||
|
|
||||||
if(CollectionUtils.nullSafeHasContents(children))
|
|
||||||
{
|
|
||||||
InsertInput insertInput = new InsertInput(executeCodeInput.getInstance());
|
|
||||||
insertInput.setSession(executeCodeInput.getSession());
|
|
||||||
insertInput.setTableName("scriptLogLine");
|
|
||||||
insertInput.setRecords(children);
|
|
||||||
new InsertAction().execute(insertInput);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
LOG.warn("Error storing script log", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for scriptLogLines
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public List<QRecord> getScriptLogLines()
|
||||||
|
{
|
||||||
|
return scriptLogLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for scriptLog
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
protected void setScriptLog(QRecord scriptLog)
|
||||||
|
{
|
||||||
|
this.scriptLog = scriptLog;
|
||||||
|
}
|
||||||
}
|
}
|
@ -33,7 +33,7 @@ import org.apache.logging.log4j.Logger;
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Implementation of a code execution logger that just logs to LOG 4j
|
** Implementation of a code execution logger that logs to LOG 4j
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class Log4jCodeExecutionLogger implements QCodeExecutionLoggerInterface
|
public class Log4jCodeExecutionLogger implements QCodeExecutionLoggerInterface
|
||||||
{
|
{
|
||||||
@ -52,8 +52,8 @@ public class Log4jCodeExecutionLogger implements QCodeExecutionLoggerInterface
|
|||||||
{
|
{
|
||||||
this.qCodeReference = executeCodeInput.getCodeReference();
|
this.qCodeReference = executeCodeInput.getCodeReference();
|
||||||
|
|
||||||
String contextString = StringUtils.safeTruncate(ValueUtils.getValueAsString(executeCodeInput.getContext()), 250, "...");
|
String inputString = StringUtils.safeTruncate(ValueUtils.getValueAsString(executeCodeInput.getInput()), 250, "...");
|
||||||
LOG.info("Starting script execution: " + qCodeReference.getName() + ", uuid: " + uuid + ", with context: " + contextString);
|
LOG.info("Starting script execution: " + qCodeReference.getName() + ", uuid: " + uuid + ", with input: " + inputString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,23 +27,24 @@ import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Interface to provide logging functionality to QCodeExecution (e.g., scripts)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public interface QCodeExecutionLoggerInterface
|
public interface QCodeExecutionLoggerInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Called when the execution starts - takes the execution's input object.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
void acceptExecutionStart(ExecuteCodeInput executeCodeInput);
|
void acceptExecutionStart(ExecuteCodeInput executeCodeInput);
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Called to log a line, a message.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
void acceptLogLine(String logLine);
|
void acceptLogLine(String logLine);
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** In case the loggerInterface object is provided to the script as context,
|
||||||
|
** this method gives a clean interface for the script to log a line.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
default void log(String message)
|
default void log(String message)
|
||||||
{
|
{
|
||||||
@ -51,12 +52,12 @@ public interface QCodeExecutionLoggerInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Called if the script fails with an exception.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
void acceptException(Exception exception);
|
void acceptException(Exception exception);
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Called if the script completes without exception.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
void acceptExecutionEnd(Serializable output);
|
void acceptExecutionEnd(Serializable output);
|
||||||
|
|
||||||
|
@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.actions.scripts.logging;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Implementation of a code execution logger that logs into scriptLog and scriptLogLine
|
||||||
|
** tables - e.g., as defined in ScriptMetaDataProvider.
|
||||||
|
*******************************************************************************/
|
||||||
|
public class StoreScriptLogAndScriptLogLineExecutionLogger extends BuildScriptLogAndScriptLogLineExecutionLogger
|
||||||
|
{
|
||||||
|
private static final Logger LOG = LogManager.getLogger(StoreScriptLogAndScriptLogLineExecutionLogger.class);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Constructor
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public StoreScriptLogAndScriptLogLineExecutionLogger(Serializable scriptId, Serializable scriptRevisionId)
|
||||||
|
{
|
||||||
|
super(scriptId, scriptRevisionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public void acceptExecutionStart(ExecuteCodeInput executeCodeInput)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
super.acceptExecutionStart(executeCodeInput);
|
||||||
|
|
||||||
|
InsertInput insertInput = new InsertInput(executeCodeInput.getInstance());
|
||||||
|
insertInput.setSession(executeCodeInput.getSession());
|
||||||
|
insertInput.setTableName("scriptLog");
|
||||||
|
insertInput.setRecords(List.of(getScriptLog()));
|
||||||
|
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||||
|
|
||||||
|
setScriptLog(insertOutput.getRecords().get(0));
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
LOG.warn("Error starting storage of script log", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public void acceptException(Exception exception)
|
||||||
|
{
|
||||||
|
store(null, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public void acceptExecutionEnd(Serializable output)
|
||||||
|
{
|
||||||
|
store(output, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void store(Serializable output, Exception exception)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
updateHeaderAtEnd(output, exception);
|
||||||
|
UpdateInput updateInput = new UpdateInput(executeCodeInput.getInstance());
|
||||||
|
updateInput.setSession(executeCodeInput.getSession());
|
||||||
|
updateInput.setTableName("scriptLog");
|
||||||
|
updateInput.setRecords(List.of(getScriptLog()));
|
||||||
|
new UpdateAction().execute(updateInput);
|
||||||
|
|
||||||
|
if(CollectionUtils.nullSafeHasContents(getScriptLogLines()))
|
||||||
|
{
|
||||||
|
InsertInput insertInput = new InsertInput(executeCodeInput.getInstance());
|
||||||
|
insertInput.setSession(executeCodeInput.getSession());
|
||||||
|
insertInput.setTableName("scriptLogLine");
|
||||||
|
insertInput.setRecords(getScriptLogLines());
|
||||||
|
new InsertAction().execute(insertInput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
LOG.warn("Error storing script log", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -406,8 +406,11 @@ public class QPossibleValueTranslator
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// this is needed to get record labels, which are what we use here... unclear if best! //
|
// this is needed to get record labels, which are what we use here... unclear if best! //
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
if(notTooDeep())
|
||||||
|
{
|
||||||
queryInput.setShouldTranslatePossibleValues(true);
|
queryInput.setShouldTranslatePossibleValues(true);
|
||||||
queryInput.setShouldGenerateDisplayValues(true);
|
queryInput.setShouldGenerateDisplayValues(true);
|
||||||
|
}
|
||||||
|
|
||||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||||
|
|
||||||
@ -428,4 +431,24 @@ public class QPossibleValueTranslator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Avoid infinite recursion, for where one field's PVS depends on another's...
|
||||||
|
** not too smart, just breaks at 5...
|
||||||
|
*******************************************************************************/
|
||||||
|
private boolean notTooDeep()
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
for(StackTraceElement stackTraceElement : new Throwable().getStackTrace())
|
||||||
|
{
|
||||||
|
if(stackTraceElement.getMethodName().equals("translatePossibleValuesInRecords"))
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (count < 5);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -184,6 +184,7 @@ public class QValueFormatter
|
|||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
|
LOG.debug("Error formatting record label", e);
|
||||||
return (formatRecordLabelExceptionalCases(table, record));
|
return (formatRecordLabelExceptionalCases(table, record));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,10 @@ package com.kingsrook.qqq.backend.core.exceptions;
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Exception thrown while generating reports
|
** Exception thrown while executing custom code in QQQ.
|
||||||
*
|
**
|
||||||
|
** Context field is meant to give the user "context" for where the error occurred
|
||||||
|
** - e.g., a line number or word that was bad.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class QCodeException extends QException
|
public class QCodeException extends QException
|
||||||
{
|
{
|
||||||
|
@ -37,6 +37,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
|||||||
public class ExecuteCodeInput extends AbstractActionInput
|
public class ExecuteCodeInput extends AbstractActionInput
|
||||||
{
|
{
|
||||||
private QCodeReference codeReference;
|
private QCodeReference codeReference;
|
||||||
|
private Map<String, Serializable> input;
|
||||||
private Map<String, Serializable> context;
|
private Map<String, Serializable> context;
|
||||||
private QCodeExecutionLoggerInterface executionLogger;
|
private QCodeExecutionLoggerInterface executionLogger;
|
||||||
|
|
||||||
@ -87,6 +88,56 @@ public class ExecuteCodeInput extends AbstractActionInput
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for input
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Map<String, Serializable> getInput()
|
||||||
|
{
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for input
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setInput(Map<String, Serializable> input)
|
||||||
|
{
|
||||||
|
this.input = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for input
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public ExecuteCodeInput withInput(Map<String, Serializable> input)
|
||||||
|
{
|
||||||
|
this.input = input;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for input
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public ExecuteCodeInput withInput(String key, Serializable value)
|
||||||
|
{
|
||||||
|
if(this.input == null)
|
||||||
|
{
|
||||||
|
input = new HashMap<>();
|
||||||
|
}
|
||||||
|
this.input.put(key, value);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for context
|
** Getter for context
|
||||||
**
|
**
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
package com.kingsrook.qqq.backend.core.model.actions.scripts;
|
package com.kingsrook.qqq.backend.core.model.actions.scripts;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
|
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
@ -34,7 +35,9 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.AssociatedScriptCodeRe
|
|||||||
public class RunAssociatedScriptInput extends AbstractTableActionInput
|
public class RunAssociatedScriptInput extends AbstractTableActionInput
|
||||||
{
|
{
|
||||||
private AssociatedScriptCodeReference codeReference;
|
private AssociatedScriptCodeReference codeReference;
|
||||||
private Map<String, String> inputValues;
|
private Map<String, Serializable> inputValues;
|
||||||
|
|
||||||
|
private Serializable outputObject;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -86,7 +89,7 @@ public class RunAssociatedScriptInput extends AbstractTableActionInput
|
|||||||
** Getter for inputValues
|
** Getter for inputValues
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public Map<String, String> getInputValues()
|
public Map<String, Serializable> getInputValues()
|
||||||
{
|
{
|
||||||
return inputValues;
|
return inputValues;
|
||||||
}
|
}
|
||||||
@ -97,7 +100,7 @@ public class RunAssociatedScriptInput extends AbstractTableActionInput
|
|||||||
** Setter for inputValues
|
** Setter for inputValues
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public void setInputValues(Map<String, String> inputValues)
|
public void setInputValues(Map<String, Serializable> inputValues)
|
||||||
{
|
{
|
||||||
this.inputValues = inputValues;
|
this.inputValues = inputValues;
|
||||||
}
|
}
|
||||||
@ -108,10 +111,44 @@ public class RunAssociatedScriptInput extends AbstractTableActionInput
|
|||||||
** Fluent setter for inputValues
|
** Fluent setter for inputValues
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public RunAssociatedScriptInput withInputValues(Map<String, String> inputValues)
|
public RunAssociatedScriptInput withInputValues(Map<String, Serializable> inputValues)
|
||||||
{
|
{
|
||||||
this.inputValues = inputValues;
|
this.inputValues = inputValues;
|
||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for outputObject
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Serializable getOutputObject()
|
||||||
|
{
|
||||||
|
return outputObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for outputObject
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setOutputObject(Serializable outputObject)
|
||||||
|
{
|
||||||
|
this.outputObject = outputObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for outputObject
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public RunAssociatedScriptInput withOutputObject(Serializable outputObject)
|
||||||
|
{
|
||||||
|
this.outputObject = outputObject;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,12 @@
|
|||||||
package com.kingsrook.qqq.backend.core.model.metadata;
|
package com.kingsrook.qqq.backend.core.model.metadata;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.serialization.QBackendMetaDataDeserializer;
|
import com.kingsrook.qqq.backend.core.model.metadata.serialization.QBackendMetaDataDeserializer;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.Capability;
|
||||||
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface;
|
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface;
|
||||||
|
|
||||||
|
|
||||||
@ -38,6 +42,9 @@ public class QBackendMetaData
|
|||||||
private String name;
|
private String name;
|
||||||
private String backendType;
|
private String backendType;
|
||||||
|
|
||||||
|
private Set<Capability> enabledCapabilities = new HashSet<>();
|
||||||
|
private Set<Capability> disabledCapabilities = new HashSet<>();
|
||||||
|
|
||||||
// todo - at some point, we may want to apply this to secret properties on subclasses?
|
// todo - at some point, we may want to apply this to secret properties on subclasses?
|
||||||
// @JsonFilter("secretsFilter")
|
// @JsonFilter("secretsFilter")
|
||||||
|
|
||||||
@ -157,4 +164,161 @@ public class QBackendMetaData
|
|||||||
// noop in base class //
|
// noop in base class //
|
||||||
////////////////////////
|
////////////////////////
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for enabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Set<Capability> getEnabledCapabilities()
|
||||||
|
{
|
||||||
|
return enabledCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for enabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setEnabledCapabilities(Set<Capability> enabledCapabilities)
|
||||||
|
{
|
||||||
|
this.enabledCapabilities = enabledCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for enabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QBackendMetaData withEnabledCapabilities(Set<Capability> enabledCapabilities)
|
||||||
|
{
|
||||||
|
this.enabledCapabilities = enabledCapabilities;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Alternative fluent setter for enabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QBackendMetaData withCapabilities(Set<Capability> enabledCapabilities)
|
||||||
|
{
|
||||||
|
this.enabledCapabilities = enabledCapabilities;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Alternative fluent setter for a single enabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QBackendMetaData withCapability(Capability capability)
|
||||||
|
{
|
||||||
|
if(this.enabledCapabilities == null)
|
||||||
|
{
|
||||||
|
this.enabledCapabilities = new HashSet<>();
|
||||||
|
}
|
||||||
|
this.enabledCapabilities.add(capability);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for enabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QBackendMetaData withCapabilities(Capability... enabledCapabilities)
|
||||||
|
{
|
||||||
|
if(this.enabledCapabilities == null)
|
||||||
|
{
|
||||||
|
this.enabledCapabilities = new HashSet<>();
|
||||||
|
}
|
||||||
|
this.enabledCapabilities.addAll(Arrays.stream(enabledCapabilities).toList());
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for disabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Set<Capability> getDisabledCapabilities()
|
||||||
|
{
|
||||||
|
return disabledCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for disabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setDisabledCapabilities(Set<Capability> disabledCapabilities)
|
||||||
|
{
|
||||||
|
this.disabledCapabilities = disabledCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for disabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QBackendMetaData withDisabledCapabilities(Set<Capability> disabledCapabilities)
|
||||||
|
{
|
||||||
|
this.disabledCapabilities = disabledCapabilities;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for disabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QBackendMetaData withoutCapabilities(Capability... disabledCapabilities)
|
||||||
|
{
|
||||||
|
if(this.disabledCapabilities == null)
|
||||||
|
{
|
||||||
|
this.disabledCapabilities = new HashSet<>();
|
||||||
|
}
|
||||||
|
this.disabledCapabilities.addAll(Arrays.stream(disabledCapabilities).toList());
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Alternative fluent setter for disabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QBackendMetaData withoutCapabilities(Set<Capability> disabledCapabilities)
|
||||||
|
{
|
||||||
|
this.disabledCapabilities = disabledCapabilities;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Alternative fluent setter for a single disabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QBackendMetaData withoutCapability(Capability capability)
|
||||||
|
{
|
||||||
|
if(this.disabledCapabilities == null)
|
||||||
|
{
|
||||||
|
this.disabledCapabilities = new HashSet<>();
|
||||||
|
}
|
||||||
|
this.disabledCapabilities.add(capability);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,9 @@
|
|||||||
package com.kingsrook.qqq.backend.core.model.metadata.dashboard;
|
package com.kingsrook.qqq.backend.core.model.metadata.dashboard;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
|
|
||||||
|
|
||||||
@ -38,6 +41,8 @@ public class QWidgetMetaData implements QWidgetMetaDataInterface
|
|||||||
protected Integer gridColumns;
|
protected Integer gridColumns;
|
||||||
protected QCodeReference codeReference;
|
protected QCodeReference codeReference;
|
||||||
|
|
||||||
|
protected Map<String, Serializable> defaultValues = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -242,4 +247,56 @@ public class QWidgetMetaData implements QWidgetMetaDataInterface
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for defaultValues
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Map<String, Serializable> getDefaultValues()
|
||||||
|
{
|
||||||
|
return defaultValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for defaultValues
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setDefaultValues(Map<String, Serializable> defaultValues)
|
||||||
|
{
|
||||||
|
this.defaultValues = defaultValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for defaultValues
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QWidgetMetaData withDefaultValues(Map<String, Serializable> defaultValues)
|
||||||
|
{
|
||||||
|
this.defaultValues = defaultValues;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for a single defaultValue
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QWidgetMetaData withDefaultValue(String key, Serializable value)
|
||||||
|
{
|
||||||
|
if(this.defaultValues == null)
|
||||||
|
{
|
||||||
|
this.defaultValues = new LinkedHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.defaultValues.put(key, value);
|
||||||
|
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,11 @@ public enum AdornmentType
|
|||||||
{
|
{
|
||||||
LINK,
|
LINK,
|
||||||
CHIP,
|
CHIP,
|
||||||
SIZE;
|
SIZE,
|
||||||
|
CODE_EDITOR;
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// keep these values in sync with AdornmentType.ts in qqq-frontend-core //
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,11 +23,16 @@ package com.kingsrook.qqq.backend.core.model.metadata.frontend;
|
|||||||
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.Capability;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QFieldSection;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QFieldSection;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
@ -53,6 +58,8 @@ public class QFrontendTableMetaData
|
|||||||
|
|
||||||
private List<String> widgets;
|
private List<String> widgets;
|
||||||
|
|
||||||
|
private Set<String> capabilities;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
// do not add setters. take values from the source-object in the constructor!! //
|
// do not add setters. take values from the source-object in the constructor!! //
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -62,7 +69,7 @@ public class QFrontendTableMetaData
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public QFrontendTableMetaData(QTableMetaData tableMetaData, boolean includeFields)
|
public QFrontendTableMetaData(QBackendMetaData backendForTable, QTableMetaData tableMetaData, boolean includeFields)
|
||||||
{
|
{
|
||||||
this.name = tableMetaData.getName();
|
this.name = tableMetaData.getName();
|
||||||
this.label = tableMetaData.getLabel();
|
this.label = tableMetaData.getLabel();
|
||||||
@ -89,6 +96,62 @@ public class QFrontendTableMetaData
|
|||||||
{
|
{
|
||||||
this.widgets = tableMetaData.getWidgets();
|
this.widgets = tableMetaData.getWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setCapabilities(backendForTable, tableMetaData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void setCapabilities(QBackendMetaData backend, QTableMetaData table)
|
||||||
|
{
|
||||||
|
Set<Capability> enabledCapabilities = new HashSet<>();
|
||||||
|
for(Capability capability : Capability.values())
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////
|
||||||
|
// by default, every table can do everything //
|
||||||
|
///////////////////////////////////////////////
|
||||||
|
boolean hasCapability = true;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// if the table's backend says the capability is disabled, then by default, then the capability is disabled... //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
if(backend.getDisabledCapabilities().contains(capability))
|
||||||
|
{
|
||||||
|
hasCapability = false;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// unless the table overrides that and says that it IS enabled //
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
if(table.getEnabledCapabilities().contains(capability))
|
||||||
|
{
|
||||||
|
hasCapability = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// if the backend doesn't specify the capability, then disable it if the table says so //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
if(table.getDisabledCapabilities().contains(capability))
|
||||||
|
{
|
||||||
|
hasCapability = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hasCapability)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////
|
||||||
|
// todo - check if user is allowed!! //
|
||||||
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
enabledCapabilities.add(capability);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.capabilities = enabledCapabilities.stream().map(Enum::name).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -178,4 +241,16 @@ public class QFrontendTableMetaData
|
|||||||
{
|
{
|
||||||
return widgets;
|
return widgets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for capabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Set<String> getCapabilities()
|
||||||
|
{
|
||||||
|
return capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,9 @@ package com.kingsrook.qqq.backend.core.model.metadata.layout;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
|
|
||||||
|
|
||||||
@ -340,4 +343,38 @@ public class QAppMetaData implements QAppChildMetaData
|
|||||||
this.addSection(section);
|
this.addSection(section);
|
||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QAppMetaData withSectionOfChildren(QAppSection section, QAppChildMetaData... children)
|
||||||
|
{
|
||||||
|
this.addSection(section);
|
||||||
|
|
||||||
|
for(QAppChildMetaData child : children)
|
||||||
|
{
|
||||||
|
withChild(child);
|
||||||
|
if(child instanceof QTableMetaData)
|
||||||
|
{
|
||||||
|
section.withTable(child.getName());
|
||||||
|
}
|
||||||
|
else if(child instanceof QProcessMetaData)
|
||||||
|
{
|
||||||
|
section.withProcess(child.getName());
|
||||||
|
}
|
||||||
|
else if(child instanceof QReportMetaData)
|
||||||
|
{
|
||||||
|
section.withReport(child.getName());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Unrecognized child type: " + child.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
package com.kingsrook.qqq.backend.core.model.metadata.layout;
|
package com.kingsrook.qqq.backend.core.model.metadata.layout;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
@ -166,6 +167,22 @@ public class QAppSection
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for tables
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QAppSection withTable(String tableName)
|
||||||
|
{
|
||||||
|
if(this.tables == null)
|
||||||
|
{
|
||||||
|
this.tables = new ArrayList<>();
|
||||||
|
}
|
||||||
|
this.tables.add(tableName);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for processes
|
** Getter for processes
|
||||||
**
|
**
|
||||||
@ -200,6 +217,22 @@ public class QAppSection
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for processes
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QAppSection withProcess(String processName)
|
||||||
|
{
|
||||||
|
if(this.processes == null)
|
||||||
|
{
|
||||||
|
this.processes = new ArrayList<>();
|
||||||
|
}
|
||||||
|
this.processes.add(processName);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for reports
|
** Getter for reports
|
||||||
**
|
**
|
||||||
@ -234,6 +267,22 @@ public class QAppSection
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for reports
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QAppSection withReport(String reportName)
|
||||||
|
{
|
||||||
|
if(this.reports == null)
|
||||||
|
{
|
||||||
|
this.reports = new ArrayList<>();
|
||||||
|
}
|
||||||
|
this.reports.add(reportName);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for icon
|
** Getter for icon
|
||||||
**
|
**
|
||||||
|
@ -289,6 +289,7 @@ public class QPossibleValueSource
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public void setTableName(String tableName)
|
public void setTableName(String tableName)
|
||||||
{
|
{
|
||||||
|
this.type = QPossibleValueSourceType.TABLE;
|
||||||
this.tableName = tableName;
|
this.tableName = tableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,7 +301,7 @@ public class QPossibleValueSource
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public QPossibleValueSource withTableName(String tableName)
|
public QPossibleValueSource withTableName(String tableName)
|
||||||
{
|
{
|
||||||
this.tableName = tableName;
|
setTableName(tableName);
|
||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,6 +447,7 @@ public class QPossibleValueSource
|
|||||||
public void setEnumValues(List<QPossibleValue<?>> enumValues)
|
public void setEnumValues(List<QPossibleValue<?>> enumValues)
|
||||||
{
|
{
|
||||||
this.enumValues = enumValues;
|
this.enumValues = enumValues;
|
||||||
|
setType(QPossibleValueSourceType.ENUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -456,7 +458,7 @@ public class QPossibleValueSource
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public QPossibleValueSource withEnumValues(List<QPossibleValue<?>> enumValues)
|
public QPossibleValueSource withEnumValues(List<QPossibleValue<?>> enumValues)
|
||||||
{
|
{
|
||||||
this.enumValues = enumValues;
|
setEnumValues(enumValues);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,6 +474,7 @@ public class QPossibleValueSource
|
|||||||
this.enumValues = new ArrayList<>();
|
this.enumValues = new ArrayList<>();
|
||||||
}
|
}
|
||||||
this.enumValues.add(possibleValue);
|
this.enumValues.add(possibleValue);
|
||||||
|
setType(QPossibleValueSourceType.ENUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -512,6 +515,7 @@ public class QPossibleValueSource
|
|||||||
public void setCustomCodeReference(QCodeReference customCodeReference)
|
public void setCustomCodeReference(QCodeReference customCodeReference)
|
||||||
{
|
{
|
||||||
this.customCodeReference = customCodeReference;
|
this.customCodeReference = customCodeReference;
|
||||||
|
setType(QPossibleValueSourceType.CUSTOM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -522,7 +526,7 @@ public class QPossibleValueSource
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public QPossibleValueSource withCustomCodeReference(QCodeReference customCodeReference)
|
public QPossibleValueSource withCustomCodeReference(QCodeReference customCodeReference)
|
||||||
{
|
{
|
||||||
this.customCodeReference = customCodeReference;
|
setCustomCodeReference(customCodeReference);
|
||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.metadata.tables;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Things that can be done to tables, fields.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public enum Capability
|
||||||
|
{
|
||||||
|
TABLE_QUERY,
|
||||||
|
TABLE_GET,
|
||||||
|
TABLE_COUNT,
|
||||||
|
TABLE_INSERT,
|
||||||
|
TABLE_UPDATE,
|
||||||
|
TABLE_DELETE
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// keep these values in sync with AdornmentType.ts in qqq-frontend-core //
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
}
|
@ -38,6 +38,8 @@ public class QFieldSection
|
|||||||
private List<String> fieldNames;
|
private List<String> fieldNames;
|
||||||
private QIcon icon;
|
private QIcon icon;
|
||||||
|
|
||||||
|
private boolean isHidden = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -244,4 +246,38 @@ public class QFieldSection
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for isHidden
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public boolean getIsHidden()
|
||||||
|
{
|
||||||
|
return (isHidden);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for isHidden
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setIsHidden(boolean isHidden)
|
||||||
|
{
|
||||||
|
this.isHidden = isHidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent Setter for isHidden
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QFieldSection withIsHidden(boolean isHidden)
|
||||||
|
{
|
||||||
|
this.isHidden = isHidden;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,10 +26,12 @@ import java.io.Serializable;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizer;
|
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizer;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecordEntity;
|
import com.kingsrook.qqq.backend.core.model.data.QRecordEntity;
|
||||||
@ -81,6 +83,9 @@ public class QTableMetaData implements QAppChildMetaData, Serializable
|
|||||||
private List<String> widgets;
|
private List<String> widgets;
|
||||||
private List<AssociatedScript> associatedScripts;
|
private List<AssociatedScript> associatedScripts;
|
||||||
|
|
||||||
|
private Set<Capability> enabledCapabilities = new HashSet<>();
|
||||||
|
private Set<Capability> disabledCapabilities = new HashSet<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -874,4 +879,160 @@ public class QTableMetaData implements QAppChildMetaData, Serializable
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for enabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Set<Capability> getEnabledCapabilities()
|
||||||
|
{
|
||||||
|
return enabledCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for enabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setEnabledCapabilities(Set<Capability> enabledCapabilities)
|
||||||
|
{
|
||||||
|
this.enabledCapabilities = enabledCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for enabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QTableMetaData withEnabledCapabilities(Set<Capability> enabledCapabilities)
|
||||||
|
{
|
||||||
|
this.enabledCapabilities = enabledCapabilities;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Alternative fluent setter for enabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QTableMetaData withCapabilities(Set<Capability> enabledCapabilities)
|
||||||
|
{
|
||||||
|
this.enabledCapabilities = enabledCapabilities;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Alternative fluent setter for a single enabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QTableMetaData withCapability(Capability capability)
|
||||||
|
{
|
||||||
|
if(this.enabledCapabilities == null)
|
||||||
|
{
|
||||||
|
this.enabledCapabilities = new HashSet<>();
|
||||||
|
}
|
||||||
|
this.enabledCapabilities.add(capability);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for enabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QTableMetaData withCapabilities(Capability... enabledCapabilities)
|
||||||
|
{
|
||||||
|
if(this.enabledCapabilities == null)
|
||||||
|
{
|
||||||
|
this.enabledCapabilities = new HashSet<>();
|
||||||
|
}
|
||||||
|
this.enabledCapabilities.addAll(Arrays.stream(enabledCapabilities).toList());
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for disabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Set<Capability> getDisabledCapabilities()
|
||||||
|
{
|
||||||
|
return disabledCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for disabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setDisabledCapabilities(Set<Capability> disabledCapabilities)
|
||||||
|
{
|
||||||
|
this.disabledCapabilities = disabledCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for disabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QTableMetaData withDisabledCapabilities(Set<Capability> disabledCapabilities)
|
||||||
|
{
|
||||||
|
this.disabledCapabilities = disabledCapabilities;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for disabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QTableMetaData withoutCapabilities(Capability... disabledCapabilities)
|
||||||
|
{
|
||||||
|
if(this.disabledCapabilities == null)
|
||||||
|
{
|
||||||
|
this.disabledCapabilities = new HashSet<>();
|
||||||
|
}
|
||||||
|
this.disabledCapabilities.addAll(Arrays.stream(disabledCapabilities).toList());
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Alternative fluent setter for disabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QTableMetaData withoutCapabilities(Set<Capability> disabledCapabilities)
|
||||||
|
{
|
||||||
|
this.disabledCapabilities = disabledCapabilities;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Alternative fluent setter for a single disabledCapabilities
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QTableMetaData withoutCapability(Capability capability)
|
||||||
|
{
|
||||||
|
if(this.disabledCapabilities == null)
|
||||||
|
{
|
||||||
|
this.disabledCapabilities = new HashSet<>();
|
||||||
|
}
|
||||||
|
this.disabledCapabilities.add(capability);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -48,10 +48,10 @@ public class Script extends QRecordEntity
|
|||||||
@QField()
|
@QField()
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@QField()
|
@QField(possibleValueSourceName = "scriptType")
|
||||||
private Integer scriptTypeId;
|
private Integer scriptTypeId;
|
||||||
|
|
||||||
@QField()
|
@QField(possibleValueSourceName = "scriptRevision")
|
||||||
private Integer currentScriptRevisionId;
|
private Integer currentScriptRevisionId;
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ package com.kingsrook.qqq.backend.core.model.scripts;
|
|||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QField;
|
import com.kingsrook.qqq.backend.core.model.data.QField;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecordEntity;
|
import com.kingsrook.qqq.backend.core.model.data.QRecordEntity;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.DisplayFormat;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -43,10 +44,10 @@ public class ScriptLog extends QRecordEntity
|
|||||||
@QField()
|
@QField()
|
||||||
private Instant modifyDate;
|
private Instant modifyDate;
|
||||||
|
|
||||||
@QField()
|
@QField(possibleValueSourceName = "script")
|
||||||
private Integer scriptId;
|
private Integer scriptId;
|
||||||
|
|
||||||
@QField()
|
@QField(possibleValueSourceName = "scriptRevision")
|
||||||
private Integer scriptRevisionId;
|
private Integer scriptRevisionId;
|
||||||
|
|
||||||
@QField()
|
@QField()
|
||||||
@ -55,7 +56,7 @@ public class ScriptLog extends QRecordEntity
|
|||||||
@QField()
|
@QField()
|
||||||
private Instant endTimestamp;
|
private Instant endTimestamp;
|
||||||
|
|
||||||
@QField()
|
@QField(displayFormat = DisplayFormat.COMMAS)
|
||||||
private Integer runTimeMillis;
|
private Integer runTimeMillis;
|
||||||
|
|
||||||
@QField()
|
@QField()
|
||||||
|
@ -43,7 +43,7 @@ public class ScriptLogLine extends QRecordEntity
|
|||||||
@QField()
|
@QField()
|
||||||
private Instant modifyDate;
|
private Instant modifyDate;
|
||||||
|
|
||||||
@QField()
|
@QField(possibleValueSourceName = "scriptLog")
|
||||||
private Integer scriptLogId;
|
private Integer scriptLogId;
|
||||||
|
|
||||||
@QField()
|
@QField()
|
||||||
|
@ -45,7 +45,7 @@ public class ScriptRevision extends QRecordEntity
|
|||||||
@QField()
|
@QField()
|
||||||
private Instant modifyDate;
|
private Instant modifyDate;
|
||||||
|
|
||||||
@QField()
|
@QField(possibleValueSourceName = "script")
|
||||||
private Integer scriptId;
|
private Integer scriptId;
|
||||||
|
|
||||||
@QField()
|
@QField()
|
||||||
|
@ -28,7 +28,14 @@ import java.util.function.Consumer;
|
|||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecordEntity;
|
import com.kingsrook.qqq.backend.core.model.data.QRecordEntity;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.AdornmentType;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.FieldAdornment;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.Capability;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QFieldSection;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.Tier;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -37,6 +44,17 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
|||||||
public class ScriptsMetaDataProvider
|
public class ScriptsMetaDataProvider
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void defineAll(QInstance instance, String backendName, Consumer<QTableMetaData> backendDetailEnricher) throws QException
|
||||||
|
{
|
||||||
|
defineStandardScriptsTables(instance, backendName, backendDetailEnricher);
|
||||||
|
defineStandardScriptsPossibleValueSources(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -53,7 +71,35 @@ public class ScriptsMetaDataProvider
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public List<QTableMetaData> defineStandardScriptsTables(String backendName, Consumer<QTableMetaData> backendDetailEnricher) throws QException
|
public void defineStandardScriptsPossibleValueSources(QInstance instance) throws QException
|
||||||
|
{
|
||||||
|
instance.addPossibleValueSource(new QPossibleValueSource()
|
||||||
|
.withName(Script.TABLE_NAME)
|
||||||
|
.withTableName(Script.TABLE_NAME)
|
||||||
|
);
|
||||||
|
|
||||||
|
instance.addPossibleValueSource(new QPossibleValueSource()
|
||||||
|
.withName(ScriptRevision.TABLE_NAME)
|
||||||
|
.withTableName(ScriptRevision.TABLE_NAME)
|
||||||
|
);
|
||||||
|
|
||||||
|
instance.addPossibleValueSource(new QPossibleValueSource()
|
||||||
|
.withName(ScriptType.TABLE_NAME)
|
||||||
|
.withTableName(ScriptType.TABLE_NAME)
|
||||||
|
);
|
||||||
|
|
||||||
|
instance.addPossibleValueSource(new QPossibleValueSource()
|
||||||
|
.withName(ScriptLog.TABLE_NAME)
|
||||||
|
.withTableName(ScriptLog.TABLE_NAME)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private List<QTableMetaData> defineStandardScriptsTables(String backendName, Consumer<QTableMetaData> backendDetailEnricher) throws QException
|
||||||
{
|
{
|
||||||
List<QTableMetaData> rs = new ArrayList<>();
|
List<QTableMetaData> rs = new ArrayList<>();
|
||||||
rs.add(enrich(backendDetailEnricher, defineScriptTypeTable(backendName)));
|
rs.add(enrich(backendDetailEnricher, defineScriptTypeTable(backendName)));
|
||||||
@ -101,7 +147,9 @@ public class ScriptsMetaDataProvider
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private QTableMetaData defineScriptTable(String backendName) throws QException
|
private QTableMetaData defineScriptTable(String backendName) throws QException
|
||||||
{
|
{
|
||||||
return (defineStandardTable(backendName, Script.TABLE_NAME, Script.class));
|
return (defineStandardTable(backendName, Script.TABLE_NAME, Script.class)
|
||||||
|
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "name", "scriptTypeId", "currentScriptRevisionId")))
|
||||||
|
.withSection(new QFieldSection("dates", new QIcon().withName("calendar_month"), Tier.T3, List.of("createDate", "modifyDate"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -111,7 +159,12 @@ public class ScriptsMetaDataProvider
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private QTableMetaData defineScriptTypeTable(String backendName) throws QException
|
private QTableMetaData defineScriptTypeTable(String backendName) throws QException
|
||||||
{
|
{
|
||||||
return (defineStandardTable(backendName, ScriptType.TABLE_NAME, ScriptType.class));
|
QTableMetaData tableMetaData = defineStandardTable(backendName, ScriptType.TABLE_NAME, ScriptType.class)
|
||||||
|
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "name")))
|
||||||
|
.withSection(new QFieldSection("details", new QIcon().withName("dataset"), Tier.T2, List.of("helpText", "sampleCode")))
|
||||||
|
.withSection(new QFieldSection("dates", new QIcon().withName("calendar_month"), Tier.T3, List.of("createDate", "modifyDate")));
|
||||||
|
tableMetaData.getField("sampleCode").withFieldAdornment(new FieldAdornment(AdornmentType.CODE_EDITOR));
|
||||||
|
return (tableMetaData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -121,8 +174,17 @@ public class ScriptsMetaDataProvider
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private QTableMetaData defineScriptRevisionTable(String backendName) throws QException
|
private QTableMetaData defineScriptRevisionTable(String backendName) throws QException
|
||||||
{
|
{
|
||||||
return (defineStandardTable(backendName, ScriptRevision.TABLE_NAME, ScriptRevision.class)
|
QTableMetaData tableMetaData = defineStandardTable(backendName, ScriptRevision.TABLE_NAME, ScriptRevision.class)
|
||||||
.withRecordLabelFields(List.of("id")));
|
.withoutCapabilities(Capability.TABLE_INSERT, Capability.TABLE_UPDATE, Capability.TABLE_DELETE)
|
||||||
|
.withRecordLabelFormat("%s v%s")
|
||||||
|
.withRecordLabelFields(List.of("scriptId", "sequenceNo"))
|
||||||
|
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "scriptId", "sequenceNo")))
|
||||||
|
.withSection(new QFieldSection("code", new QIcon().withName("data_object"), Tier.T2, List.of("contents")))
|
||||||
|
.withSection(new QFieldSection("changeManagement", new QIcon().withName("history"), Tier.T2, List.of("commitMessage", "author")))
|
||||||
|
.withSection(new QFieldSection("dates", new QIcon().withName("calendar_month"), Tier.T3, List.of("createDate", "modifyDate")));
|
||||||
|
|
||||||
|
tableMetaData.getField("contents").withFieldAdornment(new FieldAdornment(AdornmentType.CODE_EDITOR));
|
||||||
|
return (tableMetaData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -133,7 +195,12 @@ public class ScriptsMetaDataProvider
|
|||||||
private QTableMetaData defineScriptLogTable(String backendName) throws QException
|
private QTableMetaData defineScriptLogTable(String backendName) throws QException
|
||||||
{
|
{
|
||||||
return (defineStandardTable(backendName, ScriptLog.TABLE_NAME, ScriptLog.class)
|
return (defineStandardTable(backendName, ScriptLog.TABLE_NAME, ScriptLog.class)
|
||||||
.withRecordLabelFields(List.of("id")));
|
.withRecordLabelFields(List.of("id"))
|
||||||
|
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id")))
|
||||||
|
.withSection(new QFieldSection("script", new QIcon().withName("data_object"), Tier.T2, List.of("scriptId", "scriptRevisionId")))
|
||||||
|
.withSection(new QFieldSection("timing", new QIcon().withName("schedule"), Tier.T2, List.of("startTimestamp", "endTimestamp", "runTimeMillis", "createDate", "modifyDate")))
|
||||||
|
.withSection(new QFieldSection("error", "Error", new QIcon().withName("error_outline"), Tier.T2, List.of("hadError", "error")))
|
||||||
|
.withSection(new QFieldSection("inputOutput", "Input/Output", new QIcon().withName("chat"), Tier.T2, List.of("input", "output"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,7 +28,11 @@ import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface;
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
** Backend module for a table based on a java enum. So we can expose an enum
|
||||||
|
** as a table (similar to exposing an enum as a possible value source), with multiple
|
||||||
|
** fields in the enum (exposed via getter methods in the enum) as fields in the table.
|
||||||
**
|
**
|
||||||
|
** Only supports read-operations, as you can't modify an enum.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class EnumerationBackendModule implements QBackendModuleInterface
|
public class EnumerationBackendModule implements QBackendModuleInterface
|
||||||
{
|
{
|
||||||
|
@ -39,12 +39,16 @@ import org.apache.commons.lang.NotImplementedException;
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
** Utility class for backend modules that need to do filter operations.
|
||||||
**
|
**
|
||||||
|
** e.g., like an in-memory module, or one that's working with files - basically
|
||||||
|
** one that doesn't have filtering provided by the backend (like a database or API).
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class BackendQueryFilterUtils
|
public class BackendQueryFilterUtils
|
||||||
{
|
{
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Test if record matches filter.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@SuppressWarnings("checkstyle:indentation")
|
@SuppressWarnings("checkstyle:indentation")
|
||||||
public static boolean doesRecordMatch(QQueryFilter filter, QRecord qRecord)
|
public static boolean doesRecordMatch(QQueryFilter filter, QRecord qRecord)
|
||||||
@ -407,7 +411,7 @@ public class BackendQueryFilterUtils
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Sort list of records based on filter.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static void sortRecordList(QQueryFilter filter, List<QRecord> recordList)
|
public static void sortRecordList(QQueryFilter filter, List<QRecord> recordList)
|
||||||
{
|
{
|
||||||
@ -443,7 +447,7 @@ public class BackendQueryFilterUtils
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Apply skip & limit attributes from queryInput to a list of records.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static List<QRecord> applySkipAndLimit(QueryInput queryInput, List<QRecord> recordList)
|
public static List<QRecord> applySkipAndLimit(QueryInput queryInput, List<QRecord> recordList)
|
||||||
{
|
{
|
||||||
|
@ -41,13 +41,19 @@ import com.kingsrook.qqq.backend.core.utils.ListingHash;
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Utility methods for working with QQQ records and table actions inside user -
|
||||||
|
** defined QQQ processes steps.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class GeneralProcessUtils
|
public class GeneralProcessUtils
|
||||||
{
|
{
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
** For a list of sourceRecords,
|
||||||
|
** lookup records in the foreignTableName,
|
||||||
|
** that have their foreignTablePrimaryKeyName in the sourceTableForeignKeyFieldName on the sourceRecords.
|
||||||
**
|
**
|
||||||
|
** e.g., for a list of orders (with a clientId field), build a map of client.id => client record
|
||||||
|
** via getForeignRecordMap(input, orderList, "clientId", "client", "id")
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static Map<Serializable, QRecord> getForeignRecordMap(AbstractActionInput parentActionInput, List<QRecord> sourceRecords, String sourceTableForeignKeyFieldName, String foreignTableName, String foreignTablePrimaryKeyName) throws QException
|
public static Map<Serializable, QRecord> getForeignRecordMap(AbstractActionInput parentActionInput, List<QRecord> sourceRecords, String sourceTableForeignKeyFieldName, String foreignTableName, String foreignTablePrimaryKeyName) throws QException
|
||||||
{
|
{
|
||||||
@ -69,9 +75,14 @@ public class GeneralProcessUtils
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
** For a list of sourceRecords,
|
||||||
|
** lookup records in the foreignTableName,
|
||||||
|
** that have their foreignTableForeignKeyName in the sourceTableForeignKeyFieldName on the sourceRecords.
|
||||||
**
|
**
|
||||||
|
** e.g., for a list of orders, build a ListingHash of order.id => List(OrderLine records)
|
||||||
|
** via getForeignRecordListingHashMap(input, orderList, "id", "orderLine", "orderId")
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static ListingHash<Serializable, QRecord> getForeignRecordListingHashMap(AbstractActionInput parentActionInput, List<QRecord> sourceRecords, String sourceTableForeignKeyFieldName, String foreignTableName, String foreignTablePrimaryKeyName) throws QException
|
public static ListingHash<Serializable, QRecord> getForeignRecordListingHashMap(AbstractActionInput parentActionInput, List<QRecord> sourceRecords, String sourceTableForeignKeyFieldName, String foreignTableName, String foreignTableForeignKeyName) throws QException
|
||||||
{
|
{
|
||||||
ListingHash<Serializable, QRecord> foreignRecordMap = new ListingHash<>();
|
ListingHash<Serializable, QRecord> foreignRecordMap = new ListingHash<>();
|
||||||
QueryInput queryInput = new QueryInput(parentActionInput.getInstance());
|
QueryInput queryInput = new QueryInput(parentActionInput.getInstance());
|
||||||
@ -79,11 +90,11 @@ public class GeneralProcessUtils
|
|||||||
queryInput.setTableName(foreignTableName);
|
queryInput.setTableName(foreignTableName);
|
||||||
List<Serializable> foreignIds = new ArrayList<>(sourceRecords.stream().map(r -> r.getValue(sourceTableForeignKeyFieldName)).toList());
|
List<Serializable> foreignIds = new ArrayList<>(sourceRecords.stream().map(r -> r.getValue(sourceTableForeignKeyFieldName)).toList());
|
||||||
|
|
||||||
queryInput.setFilter(new QQueryFilter().withCriteria(new QFilterCriteria(foreignTablePrimaryKeyName, QCriteriaOperator.IN, foreignIds)));
|
queryInput.setFilter(new QQueryFilter().withCriteria(new QFilterCriteria(foreignTableForeignKeyName, QCriteriaOperator.IN, foreignIds)));
|
||||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||||
for(QRecord foreignRecord : queryOutput.getRecords())
|
for(QRecord foreignRecord : queryOutput.getRecords())
|
||||||
{
|
{
|
||||||
foreignRecordMap.add(foreignRecord.getValue(foreignTablePrimaryKeyName), foreignRecord);
|
foreignRecordMap.add(foreignRecord.getValue(foreignTableForeignKeyName), foreignRecord);
|
||||||
}
|
}
|
||||||
return foreignRecordMap;
|
return foreignRecordMap;
|
||||||
}
|
}
|
||||||
@ -91,7 +102,13 @@ public class GeneralProcessUtils
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
** For a list of sourceRecords,
|
||||||
|
** lookup records in the foreignTableName,
|
||||||
|
** that have their foreignTablePrimaryKeyName in the sourceTableForeignKeyFieldName on the sourceRecords.
|
||||||
|
** and set those foreign records as a value in the sourceRecords.
|
||||||
**
|
**
|
||||||
|
** e.g., for a list of orders (with a clientId field), setValue("client", QRecord(client));
|
||||||
|
** via addForeignRecordsToRecordList(input, orderList, "clientId", "client", "id")
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static void addForeignRecordsToRecordList(AbstractActionInput parentActionInput, List<QRecord> sourceRecords, String sourceTableForeignKeyFieldName, String foreignTableName, String foreignTablePrimaryKeyName) throws QException
|
public static void addForeignRecordsToRecordList(AbstractActionInput parentActionInput, List<QRecord> sourceRecords, String sourceTableForeignKeyFieldName, String foreignTableName, String foreignTablePrimaryKeyName) throws QException
|
||||||
{
|
{
|
||||||
@ -106,11 +123,16 @@ public class GeneralProcessUtils
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
** For a list of sourceRecords,
|
||||||
|
** lookup records in the foreignTableName,
|
||||||
|
** that have their foreignTableForeignKeyName in the sourceTableForeignKeyFieldName on the sourceRecords.
|
||||||
**
|
**
|
||||||
|
** e.g., for a list of orders, setValue("orderLine", List(QRecord(orderLine)))
|
||||||
|
** via addForeignRecordsListToRecordList(input, orderList, "id", "orderLine", "orderId")
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static void addForeignRecordsListToRecordList(AbstractActionInput parentActionInput, List<QRecord> sourceRecords, String sourceTableForeignKeyFieldName, String foreignTableName, String foreignTablePrimaryKeyName) throws QException
|
public static void addForeignRecordsListToRecordList(AbstractActionInput parentActionInput, List<QRecord> sourceRecords, String sourceTableForeignKeyFieldName, String foreignTableName, String foreignTableForeignKeyName) throws QException
|
||||||
{
|
{
|
||||||
ListingHash<Serializable, QRecord> foreignRecordMap = getForeignRecordListingHashMap(parentActionInput, sourceRecords, sourceTableForeignKeyFieldName, foreignTableName, foreignTablePrimaryKeyName);
|
ListingHash<Serializable, QRecord> foreignRecordMap = getForeignRecordListingHashMap(parentActionInput, sourceRecords, sourceTableForeignKeyFieldName, foreignTableName, foreignTableForeignKeyName);
|
||||||
for(QRecord sourceRecord : sourceRecords)
|
for(QRecord sourceRecord : sourceRecords)
|
||||||
{
|
{
|
||||||
List<QRecord> foreignRecordList = foreignRecordMap.get(sourceRecord.getValue(sourceTableForeignKeyFieldName));
|
List<QRecord> foreignRecordList = foreignRecordMap.get(sourceRecord.getValue(sourceTableForeignKeyFieldName));
|
||||||
@ -131,7 +153,8 @@ public class GeneralProcessUtils
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Run a query on tableName, for where fieldName equals fieldValue, and return
|
||||||
|
** the list of QRecords.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static List<QRecord> getRecordListByField(AbstractActionInput parentActionInput, String tableName, String fieldName, Serializable fieldValue) throws QException
|
public static List<QRecord> getRecordListByField(AbstractActionInput parentActionInput, String tableName, String fieldName, Serializable fieldValue) throws QException
|
||||||
{
|
{
|
||||||
@ -146,7 +169,9 @@ public class GeneralProcessUtils
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Query to get one record by a unique key value. That field can be the primary
|
||||||
|
** key, or any other field on the table. Note, if multiple rows do match the value,
|
||||||
|
** only 1 (determined in an unspecified way) is returned.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static Optional<QRecord> getRecordById(AbstractActionInput parentActionInput, String tableName, String fieldName, Serializable fieldValue) throws QException
|
public static Optional<QRecord> getRecordById(AbstractActionInput parentActionInput, String tableName, String fieldName, Serializable fieldValue) throws QException
|
||||||
{
|
{
|
||||||
@ -162,7 +187,10 @@ public class GeneralProcessUtils
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
** Load all rows from a table.
|
||||||
**
|
**
|
||||||
|
** Note, this is inherently unsafe, if you were to call it on a table with
|
||||||
|
** too many rows... Caveat emptor.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static List<QRecord> loadTable(AbstractActionInput parentActionInput, String tableName) throws QException
|
public static List<QRecord> loadTable(AbstractActionInput parentActionInput, String tableName) throws QException
|
||||||
{
|
{
|
||||||
@ -176,7 +204,15 @@ public class GeneralProcessUtils
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
** Load all rows from a table, into a map, keyed by the keyFieldName.
|
||||||
|
**
|
||||||
** Note - null values from the key field are NOT put in the map.
|
** Note - null values from the key field are NOT put in the map.
|
||||||
|
**
|
||||||
|
** If multiple values are found for the key, they'll squash each other, and only
|
||||||
|
** one random value will appear.
|
||||||
|
**
|
||||||
|
** Also, note, this is inherently unsafe, if you were to call it on a table with
|
||||||
|
** too many rows... Caveat emptor.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static Map<Serializable, QRecord> loadTableToMap(AbstractActionInput parentActionInput, String tableName, String keyFieldName) throws QException
|
public static Map<Serializable, QRecord> loadTableToMap(AbstractActionInput parentActionInput, String tableName, String keyFieldName) throws QException
|
||||||
{
|
{
|
||||||
@ -201,7 +237,14 @@ public class GeneralProcessUtils
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
** Load all rows from a table, into a ListingHash, keyed by the keyFieldName.
|
||||||
|
**
|
||||||
** Note - null values from the key field are NOT put in the map.
|
** Note - null values from the key field are NOT put in the map.
|
||||||
|
**
|
||||||
|
** The ordering of the records is not specified.
|
||||||
|
**
|
||||||
|
** Also, note, this is inherently unsafe, if you were to call it on a table with
|
||||||
|
** too many rows... Caveat emptor.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static ListingHash<Serializable, QRecord> loadTableToListingHash(AbstractActionInput parentActionInput, String tableName, String keyFieldName) throws QException
|
public static ListingHash<Serializable, QRecord> loadTableToListingHash(AbstractActionInput parentActionInput, String tableName, String keyFieldName) throws QException
|
||||||
{
|
{
|
||||||
|
@ -26,10 +26,10 @@ import java.io.Serializable;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.HeaderAndDetailTableCodeExecutionLogger;
|
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.Log4jCodeExecutionLogger;
|
import com.kingsrook.qqq.backend.core.actions.scripts.logging.Log4jCodeExecutionLogger;
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.NoopCodeExecutionLogger;
|
import com.kingsrook.qqq.backend.core.actions.scripts.logging.NoopCodeExecutionLogger;
|
||||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.QCodeExecutionLoggerInterface;
|
import com.kingsrook.qqq.backend.core.actions.scripts.logging.QCodeExecutionLoggerInterface;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.scripts.logging.StoreScriptLogAndScriptLogLineExecutionLogger;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QCodeException;
|
import com.kingsrook.qqq.backend.core.exceptions.QCodeException;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
||||||
@ -120,9 +120,9 @@ class ExecuteCodeActionTest
|
|||||||
void testTableLogger() throws QException
|
void testTableLogger() throws QException
|
||||||
{
|
{
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
QInstance qInstance = TestUtils.defineInstance();
|
||||||
new ScriptsMetaDataProvider().defineStandardScriptsTables(qInstance, TestUtils.MEMORY_BACKEND_NAME, null);
|
new ScriptsMetaDataProvider().defineAll(qInstance, TestUtils.MEMORY_BACKEND_NAME, null);
|
||||||
|
|
||||||
ExecuteCodeInput executeCodeInput = setupInput(qInstance, Map.of("x", 4), new HeaderAndDetailTableCodeExecutionLogger(1701, 1702));
|
ExecuteCodeInput executeCodeInput = setupInput(qInstance, Map.of("x", 4), new StoreScriptLogAndScriptLogLineExecutionLogger(1701, 1702));
|
||||||
ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput();
|
ExecuteCodeOutput executeCodeOutput = new ExecuteCodeOutput();
|
||||||
new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput);
|
new ExecuteCodeAction().run(executeCodeInput, executeCodeOutput);
|
||||||
assertEquals(16, executeCodeOutput.getOutput());
|
assertEquals(16, executeCodeOutput.getOutput());
|
||||||
|
@ -25,11 +25,17 @@ package com.kingsrook.qqq.backend.core.actions.scripts;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.RunAssociatedScriptInput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.RunAssociatedScriptInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.RunAssociatedScriptOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.RunAssociatedScriptOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.StoreAssociatedScriptInput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.StoreAssociatedScriptInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.StoreAssociatedScriptOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.StoreAssociatedScriptOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
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.QInstance;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.AssociatedScriptCodeReference;
|
import com.kingsrook.qqq.backend.core.model.metadata.code.AssociatedScriptCodeReference;
|
||||||
@ -56,24 +62,7 @@ class RunAssociatedScriptActionTest
|
|||||||
@Test
|
@Test
|
||||||
void test() throws QException
|
void test() throws QException
|
||||||
{
|
{
|
||||||
QInstance instance = TestUtils.defineInstance();
|
QInstance instance = setupInstance();
|
||||||
QTableMetaData table = instance.getTable(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
|
||||||
.withField(new QFieldMetaData("testScriptId", QFieldType.INTEGER))
|
|
||||||
.withAssociatedScript(new AssociatedScript()
|
|
||||||
.withScriptTypeId(1)
|
|
||||||
.withFieldName("testScriptId")
|
|
||||||
);
|
|
||||||
|
|
||||||
new ScriptsMetaDataProvider().defineStandardScriptsTables(instance, TestUtils.MEMORY_BACKEND_NAME, null);
|
|
||||||
|
|
||||||
TestUtils.insertRecords(instance, table, List.of(
|
|
||||||
new QRecord().withValue("id", 1),
|
|
||||||
new QRecord().withValue("id", 2)
|
|
||||||
));
|
|
||||||
|
|
||||||
TestUtils.insertRecords(instance, instance.getTable("scriptType"), List.of(
|
|
||||||
new QRecord().withValue("id", 1).withValue("name", "Test Script Type")
|
|
||||||
));
|
|
||||||
|
|
||||||
insertScript(instance, 1, """
|
insertScript(instance, 1, """
|
||||||
return "Hello";
|
return "Hello";
|
||||||
@ -90,6 +79,9 @@ class RunAssociatedScriptActionTest
|
|||||||
);
|
);
|
||||||
RunAssociatedScriptOutput runAssociatedScriptOutput = new RunAssociatedScriptOutput();
|
RunAssociatedScriptOutput runAssociatedScriptOutput = new RunAssociatedScriptOutput();
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// ok - since the core module doesn't have the javascript language support module as a dep, this action will fail - but at least we can confirm it fails with this specific exception! //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
assertThatThrownBy(() -> new RunAssociatedScriptAction().run(runAssociatedScriptInput, runAssociatedScriptOutput))
|
assertThatThrownBy(() -> new RunAssociatedScriptAction().run(runAssociatedScriptInput, runAssociatedScriptOutput))
|
||||||
.isInstanceOf(QException.class)
|
.isInstanceOf(QException.class)
|
||||||
.hasRootCauseInstanceOf(ClassNotFoundException.class)
|
.hasRootCauseInstanceOf(ClassNotFoundException.class)
|
||||||
@ -98,6 +90,204 @@ class RunAssociatedScriptActionTest
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private QInstance setupInstance() throws QException
|
||||||
|
{
|
||||||
|
QInstance instance = TestUtils.defineInstance();
|
||||||
|
QTableMetaData table = instance.getTable(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
||||||
|
.withField(new QFieldMetaData("testScriptId", QFieldType.INTEGER))
|
||||||
|
.withAssociatedScript(new AssociatedScript()
|
||||||
|
.withScriptTypeId(1)
|
||||||
|
.withFieldName("testScriptId")
|
||||||
|
);
|
||||||
|
|
||||||
|
new ScriptsMetaDataProvider().defineAll(instance, TestUtils.MEMORY_BACKEND_NAME, null);
|
||||||
|
|
||||||
|
TestUtils.insertRecords(instance, table, List.of(
|
||||||
|
new QRecord().withValue("id", 1),
|
||||||
|
new QRecord().withValue("id", 2)
|
||||||
|
));
|
||||||
|
|
||||||
|
TestUtils.insertRecords(instance, instance.getTable("scriptType"), List.of(
|
||||||
|
new QRecord().withValue("id", 1).withValue("name", "Test Script Type")
|
||||||
|
));
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testRecordNotFound() throws QException
|
||||||
|
{
|
||||||
|
QInstance instance = setupInstance();
|
||||||
|
|
||||||
|
RunAssociatedScriptInput runAssociatedScriptInput = new RunAssociatedScriptInput(instance);
|
||||||
|
runAssociatedScriptInput.setSession(new QSession());
|
||||||
|
runAssociatedScriptInput.setInputValues(Map.of());
|
||||||
|
runAssociatedScriptInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||||
|
runAssociatedScriptInput.setCodeReference(new AssociatedScriptCodeReference()
|
||||||
|
.withRecordTable(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
||||||
|
.withRecordPrimaryKey(-9999)
|
||||||
|
.withFieldName("testScriptId")
|
||||||
|
);
|
||||||
|
RunAssociatedScriptOutput runAssociatedScriptOutput = new RunAssociatedScriptOutput();
|
||||||
|
|
||||||
|
assertThatThrownBy(() -> new RunAssociatedScriptAction().run(runAssociatedScriptInput, runAssociatedScriptOutput))
|
||||||
|
.isInstanceOf(QNotFoundException.class)
|
||||||
|
.hasMessageMatching("The requested record.*was not found.*");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testNoScriptInRecord() throws QException
|
||||||
|
{
|
||||||
|
QInstance instance = setupInstance();
|
||||||
|
|
||||||
|
RunAssociatedScriptInput runAssociatedScriptInput = new RunAssociatedScriptInput(instance);
|
||||||
|
runAssociatedScriptInput.setSession(new QSession());
|
||||||
|
runAssociatedScriptInput.setInputValues(Map.of());
|
||||||
|
runAssociatedScriptInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||||
|
runAssociatedScriptInput.setCodeReference(new AssociatedScriptCodeReference()
|
||||||
|
.withRecordTable(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
||||||
|
.withRecordPrimaryKey(1)
|
||||||
|
.withFieldName("testScriptId")
|
||||||
|
);
|
||||||
|
RunAssociatedScriptOutput runAssociatedScriptOutput = new RunAssociatedScriptOutput();
|
||||||
|
|
||||||
|
assertThatThrownBy(() -> new RunAssociatedScriptAction().run(runAssociatedScriptInput, runAssociatedScriptOutput))
|
||||||
|
.isInstanceOf(QNotFoundException.class)
|
||||||
|
.hasMessageMatching("The input record.*does not have a script specified for.*");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testBadScriptIdInRecord() throws QException
|
||||||
|
{
|
||||||
|
QInstance instance = setupInstance();
|
||||||
|
|
||||||
|
UpdateInput updateInput = new UpdateInput(instance);
|
||||||
|
updateInput.setSession(new QSession());
|
||||||
|
updateInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||||
|
updateInput.setRecords(List.of(new QRecord().withValue("id", 1).withValue("testScriptId", -9998)));
|
||||||
|
new UpdateAction().execute(updateInput);
|
||||||
|
|
||||||
|
RunAssociatedScriptInput runAssociatedScriptInput = new RunAssociatedScriptInput(instance);
|
||||||
|
runAssociatedScriptInput.setSession(new QSession());
|
||||||
|
runAssociatedScriptInput.setInputValues(Map.of());
|
||||||
|
runAssociatedScriptInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||||
|
runAssociatedScriptInput.setCodeReference(new AssociatedScriptCodeReference()
|
||||||
|
.withRecordTable(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
||||||
|
.withRecordPrimaryKey(1)
|
||||||
|
.withFieldName("testScriptId")
|
||||||
|
);
|
||||||
|
RunAssociatedScriptOutput runAssociatedScriptOutput = new RunAssociatedScriptOutput();
|
||||||
|
|
||||||
|
assertThatThrownBy(() -> new RunAssociatedScriptAction().run(runAssociatedScriptInput, runAssociatedScriptOutput))
|
||||||
|
.isInstanceOf(QNotFoundException.class)
|
||||||
|
.hasMessageMatching("The script for record .* was not found.*");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testNoCurrentScriptRevisionOnScript() throws QException
|
||||||
|
{
|
||||||
|
QInstance instance = setupInstance();
|
||||||
|
|
||||||
|
insertScript(instance, 1, """
|
||||||
|
return "Hello";
|
||||||
|
""");
|
||||||
|
|
||||||
|
GetInput getInput = new GetInput(instance);
|
||||||
|
getInput.setSession(new QSession());
|
||||||
|
getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||||
|
getInput.setPrimaryKey(1);
|
||||||
|
GetOutput getOutput = new GetAction().execute(getInput);
|
||||||
|
Integer scriptId = getOutput.getRecord().getValueInteger("testScriptId");
|
||||||
|
|
||||||
|
UpdateInput updateInput = new UpdateInput(instance);
|
||||||
|
updateInput.setSession(new QSession());
|
||||||
|
updateInput.setTableName("script");
|
||||||
|
updateInput.setRecords(List.of(new QRecord().withValue("id", scriptId).withValue("currentScriptRevisionId", null)));
|
||||||
|
new UpdateAction().execute(updateInput);
|
||||||
|
|
||||||
|
RunAssociatedScriptInput runAssociatedScriptInput = new RunAssociatedScriptInput(instance);
|
||||||
|
runAssociatedScriptInput.setSession(new QSession());
|
||||||
|
runAssociatedScriptInput.setInputValues(Map.of());
|
||||||
|
runAssociatedScriptInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||||
|
runAssociatedScriptInput.setCodeReference(new AssociatedScriptCodeReference()
|
||||||
|
.withRecordTable(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
||||||
|
.withRecordPrimaryKey(1)
|
||||||
|
.withFieldName("testScriptId")
|
||||||
|
);
|
||||||
|
RunAssociatedScriptOutput runAssociatedScriptOutput = new RunAssociatedScriptOutput();
|
||||||
|
|
||||||
|
assertThatThrownBy(() -> new RunAssociatedScriptAction().run(runAssociatedScriptInput, runAssociatedScriptOutput))
|
||||||
|
.isInstanceOf(QNotFoundException.class)
|
||||||
|
.hasMessageMatching("The script for record .* does not have a current version.*");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testBadCurrentScriptRevisionOnScript() throws QException
|
||||||
|
{
|
||||||
|
QInstance instance = setupInstance();
|
||||||
|
|
||||||
|
insertScript(instance, 1, """
|
||||||
|
return "Hello";
|
||||||
|
""");
|
||||||
|
|
||||||
|
GetInput getInput = new GetInput(instance);
|
||||||
|
getInput.setSession(new QSession());
|
||||||
|
getInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||||
|
getInput.setPrimaryKey(1);
|
||||||
|
GetOutput getOutput = new GetAction().execute(getInput);
|
||||||
|
Integer scriptId = getOutput.getRecord().getValueInteger("testScriptId");
|
||||||
|
|
||||||
|
UpdateInput updateInput = new UpdateInput(instance);
|
||||||
|
updateInput.setSession(new QSession());
|
||||||
|
updateInput.setTableName("script");
|
||||||
|
updateInput.setRecords(List.of(new QRecord().withValue("id", scriptId).withValue("currentScriptRevisionId", 9997)));
|
||||||
|
new UpdateAction().execute(updateInput);
|
||||||
|
|
||||||
|
RunAssociatedScriptInput runAssociatedScriptInput = new RunAssociatedScriptInput(instance);
|
||||||
|
runAssociatedScriptInput.setSession(new QSession());
|
||||||
|
runAssociatedScriptInput.setInputValues(Map.of());
|
||||||
|
runAssociatedScriptInput.setTableName(TestUtils.TABLE_NAME_PERSON_MEMORY);
|
||||||
|
runAssociatedScriptInput.setCodeReference(new AssociatedScriptCodeReference()
|
||||||
|
.withRecordTable(TestUtils.TABLE_NAME_PERSON_MEMORY)
|
||||||
|
.withRecordPrimaryKey(1)
|
||||||
|
.withFieldName("testScriptId")
|
||||||
|
);
|
||||||
|
RunAssociatedScriptOutput runAssociatedScriptOutput = new RunAssociatedScriptOutput();
|
||||||
|
|
||||||
|
assertThatThrownBy(() -> new RunAssociatedScriptAction().run(runAssociatedScriptInput, runAssociatedScriptOutput))
|
||||||
|
.isInstanceOf(QNotFoundException.class)
|
||||||
|
.hasMessageMatching("The current revision of the script for record .* was not found.*");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -24,15 +24,12 @@ package com.kingsrook.qqq.backend.core.actions.scripts;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.StoreAssociatedScriptInput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.StoreAssociatedScriptInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.StoreAssociatedScriptOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.StoreAssociatedScriptOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
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.QInstance;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
@ -47,6 +44,7 @@ import org.junit.jupiter.api.AfterEach;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -85,7 +83,7 @@ class StoreAssociatedScriptActionTest
|
|||||||
.withFieldName("otherScriptId")
|
.withFieldName("otherScriptId")
|
||||||
);
|
);
|
||||||
|
|
||||||
new ScriptsMetaDataProvider().defineStandardScriptsTables(instance, TestUtils.MEMORY_BACKEND_NAME, null);
|
new ScriptsMetaDataProvider().defineAll(instance, TestUtils.MEMORY_BACKEND_NAME, null);
|
||||||
|
|
||||||
TestUtils.insertRecords(instance, table, List.of(
|
TestUtils.insertRecords(instance, table, List.of(
|
||||||
new QRecord().withValue("id", 1),
|
new QRecord().withValue("id", 1),
|
||||||
@ -149,7 +147,6 @@ class StoreAssociatedScriptActionTest
|
|||||||
assertValueInField(instance, TestUtils.TABLE_NAME_PERSON_MEMORY, 1, "testScriptId", 1);
|
assertValueInField(instance, TestUtils.TABLE_NAME_PERSON_MEMORY, 1, "testScriptId", 1);
|
||||||
assertValueInField(instance, TestUtils.TABLE_NAME_PERSON_MEMORY, 1, "otherScriptId", 3);
|
assertValueInField(instance, TestUtils.TABLE_NAME_PERSON_MEMORY, 1, "otherScriptId", 3);
|
||||||
assertValueInField(instance, "script", 3, "currentScriptRevisionId", 4);
|
assertValueInField(instance, "script", 3, "currentScriptRevisionId", 4);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -157,16 +154,19 @@ class StoreAssociatedScriptActionTest
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private Serializable assertValueInField(QInstance instance, String tableName, Serializable recordId, String fieldName, Serializable value) throws QException
|
private void assertValueInField(QInstance instance, String tableName, Serializable recordId, String fieldName, Serializable value) throws QException
|
||||||
{
|
{
|
||||||
QueryInput queryInput = new QueryInput(instance);
|
GetInput getInput = new GetInput(instance);
|
||||||
queryInput.setSession(new QSession());
|
getInput.setSession(new QSession());
|
||||||
queryInput.setTableName(tableName);
|
getInput.setTableName(tableName);
|
||||||
queryInput.setFilter(new QQueryFilter().withCriteria(new QFilterCriteria("id", QCriteriaOperator.EQUALS, List.of(recordId))));
|
getInput.setPrimaryKey(recordId);
|
||||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
GetOutput getOutput = new GetAction().execute(getInput);
|
||||||
Serializable actual = queryOutput.getRecords().get(0).getValue(fieldName);
|
if(getOutput.getRecord() == null)
|
||||||
assertEquals(value, actual);
|
{
|
||||||
return (actual);
|
fail("Expected value [" + value + "] in field [" + fieldName + "], record [" + tableName + "][" + recordId + "], but the record wasn't found...");
|
||||||
|
}
|
||||||
|
Serializable actual = getOutput.getRecord().getValue(fieldName);
|
||||||
|
assertEquals(value, actual, "Expected value in field [" + fieldName + "], record [" + tableName + "][" + recordId + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -27,6 +27,7 @@ import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptInput;
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.TestScriptOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
|
||||||
@ -39,6 +40,7 @@ class TestScriptActionTest
|
|||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("Not yet done.")
|
||||||
void test() throws QException
|
void test() throws QException
|
||||||
{
|
{
|
||||||
QInstance instance = TestUtils.defineInstance();
|
QInstance instance = TestUtils.defineInstance();
|
||||||
|
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.actions.scripts.logging;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
||||||
|
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.scripts.ScriptsMetaDataProvider;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||||
|
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.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Unit test for BuildScriptLogAndScriptLogLineExecutionLogger
|
||||||
|
*******************************************************************************/
|
||||||
|
class BuildScriptLogAndScriptLogLineExecutionLoggerTest
|
||||||
|
{
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void test() throws QException
|
||||||
|
{
|
||||||
|
QInstance instance = TestUtils.defineInstance();
|
||||||
|
new ScriptsMetaDataProvider().defineAll(instance, TestUtils.MEMORY_BACKEND_NAME, null);
|
||||||
|
ExecuteCodeInput executeCodeInput = new ExecuteCodeInput(instance);
|
||||||
|
executeCodeInput.setSession(new QSession());
|
||||||
|
executeCodeInput.setInput(Map.of("a", 1));
|
||||||
|
|
||||||
|
BuildScriptLogAndScriptLogLineExecutionLogger logger = new BuildScriptLogAndScriptLogLineExecutionLogger(9999, 8888);
|
||||||
|
logger.acceptExecutionStart(executeCodeInput);
|
||||||
|
logger.acceptLogLine("This is a log");
|
||||||
|
logger.acceptLogLine("This is also a log");
|
||||||
|
logger.acceptExecutionEnd(true);
|
||||||
|
|
||||||
|
QRecord scriptLog = logger.getScriptLog();
|
||||||
|
assertNull(scriptLog.getValueInteger("id"));
|
||||||
|
assertNotNull(scriptLog.getValue("startTimestamp"));
|
||||||
|
assertNotNull(scriptLog.getValue("endTimestamp"));
|
||||||
|
assertNotNull(scriptLog.getValue("runTimeMillis"));
|
||||||
|
assertEquals(9999, scriptLog.getValueInteger("scriptId"));
|
||||||
|
assertEquals(8888, scriptLog.getValueInteger("scriptRevisionId"));
|
||||||
|
assertEquals("{a=1}", scriptLog.getValueString("input"));
|
||||||
|
assertEquals("true", scriptLog.getValueString("output"));
|
||||||
|
assertNull(scriptLog.getValueString("exception"));
|
||||||
|
assertFalse(scriptLog.getValueBoolean("hadError"));
|
||||||
|
|
||||||
|
List<QRecord> scriptLogLineRecords = logger.getScriptLogLines();
|
||||||
|
assertEquals(2, scriptLogLineRecords.size());
|
||||||
|
QRecord scriptLogLine = scriptLogLineRecords.get(0);
|
||||||
|
assertNull(scriptLogLine.getValueInteger("scriptLogId"));
|
||||||
|
assertNotNull(scriptLogLine.getValue("timestamp"));
|
||||||
|
assertEquals("This is a log", scriptLogLine.getValueString("text"));
|
||||||
|
scriptLogLine = scriptLogLineRecords.get(1);
|
||||||
|
assertEquals("This is also a log", scriptLogLine.getValueString("text"));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.actions.scripts.logging;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.scripts.ExecuteCodeInput;
|
||||||
|
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.scripts.ScriptsMetaDataProvider;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||||
|
import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryRecordStore;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Unit test for StoreScriptLogAndScriptLogLineExecutionLogger
|
||||||
|
*******************************************************************************/
|
||||||
|
class StoreScriptLogAndScriptLogLineExecutionLoggerTest
|
||||||
|
{
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@BeforeEach
|
||||||
|
@AfterEach
|
||||||
|
void beforeAndAfterEach()
|
||||||
|
{
|
||||||
|
MemoryRecordStore.getInstance().reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void test() throws QException
|
||||||
|
{
|
||||||
|
QInstance instance = TestUtils.defineInstance();
|
||||||
|
new ScriptsMetaDataProvider().defineAll(instance, TestUtils.MEMORY_BACKEND_NAME, null);
|
||||||
|
ExecuteCodeInput executeCodeInput = new ExecuteCodeInput(instance);
|
||||||
|
executeCodeInput.setSession(new QSession());
|
||||||
|
executeCodeInput.setInput(Map.of("a", 1));
|
||||||
|
|
||||||
|
StoreScriptLogAndScriptLogLineExecutionLogger logger = new StoreScriptLogAndScriptLogLineExecutionLogger(9999, 8888);
|
||||||
|
logger.acceptExecutionStart(executeCodeInput);
|
||||||
|
logger.acceptLogLine("This is a log");
|
||||||
|
logger.acceptLogLine("This is also a log");
|
||||||
|
logger.acceptExecutionEnd(true);
|
||||||
|
|
||||||
|
List<QRecord> scriptLogRecords = TestUtils.queryTable(instance, "scriptLog");
|
||||||
|
assertEquals(1, scriptLogRecords.size());
|
||||||
|
QRecord scriptLog = scriptLogRecords.get(0);
|
||||||
|
assertNotNull(scriptLog.getValueInteger("id"));
|
||||||
|
assertNotNull(scriptLog.getValue("startTimestamp"));
|
||||||
|
assertNotNull(scriptLog.getValue("endTimestamp"));
|
||||||
|
assertNotNull(scriptLog.getValue("runTimeMillis"));
|
||||||
|
assertEquals(9999, scriptLog.getValueInteger("scriptId"));
|
||||||
|
assertEquals(8888, scriptLog.getValueInteger("scriptRevisionId"));
|
||||||
|
assertEquals("{a=1}", scriptLog.getValueString("input"));
|
||||||
|
assertEquals("true", scriptLog.getValueString("output"));
|
||||||
|
assertNull(scriptLog.getValueString("exception"));
|
||||||
|
assertFalse(scriptLog.getValueBoolean("hadError"));
|
||||||
|
|
||||||
|
List<QRecord> scriptLogLineRecords = TestUtils.queryTable(instance, "scriptLogLine");
|
||||||
|
assertEquals(2, scriptLogLineRecords.size());
|
||||||
|
QRecord scriptLogLine = scriptLogLineRecords.get(0);
|
||||||
|
assertEquals(scriptLog.getValueInteger("id"), scriptLogLine.getValueInteger("scriptLogId"));
|
||||||
|
assertNotNull(scriptLogLine.getValue("timestamp"));
|
||||||
|
assertEquals("This is a log", scriptLogLine.getValueString("text"));
|
||||||
|
scriptLogLine = scriptLogLineRecords.get(1);
|
||||||
|
assertEquals("This is also a log", scriptLogLine.getValueString("text"));
|
||||||
|
}
|
||||||
|
}
|
@ -51,6 +51,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppSection;
|
|||||||
import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon;
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValue;
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValue;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
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.QProcessMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.queues.SQSQueueProviderMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.queues.SQSQueueProviderMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QFieldSection;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QFieldSection;
|
||||||
@ -805,6 +806,7 @@ class QInstanceValidatorTest
|
|||||||
possibleValueSource.setOrderByFields(List.of(new QFilterOrderBy("id")));
|
possibleValueSource.setOrderByFields(List.of(new QFilterOrderBy("id")));
|
||||||
possibleValueSource.setCustomCodeReference(new QCodeReference());
|
possibleValueSource.setCustomCodeReference(new QCodeReference());
|
||||||
possibleValueSource.setEnumValues(null);
|
possibleValueSource.setEnumValues(null);
|
||||||
|
possibleValueSource.setType(QPossibleValueSourceType.ENUM);
|
||||||
},
|
},
|
||||||
"should not have a tableName",
|
"should not have a tableName",
|
||||||
"should not have searchFields",
|
"should not have searchFields",
|
||||||
@ -831,6 +833,7 @@ class QInstanceValidatorTest
|
|||||||
possibleValueSource.setOrderByFields(new ArrayList<>());
|
possibleValueSource.setOrderByFields(new ArrayList<>());
|
||||||
possibleValueSource.setCustomCodeReference(new QCodeReference());
|
possibleValueSource.setCustomCodeReference(new QCodeReference());
|
||||||
possibleValueSource.setEnumValues(List.of(new QPossibleValue<>("test")));
|
possibleValueSource.setEnumValues(List.of(new QPossibleValue<>("test")));
|
||||||
|
possibleValueSource.setType(QPossibleValueSourceType.TABLE);
|
||||||
},
|
},
|
||||||
"should not have enum values",
|
"should not have enum values",
|
||||||
"should not have a customCodeReference",
|
"should not have a customCodeReference",
|
||||||
@ -860,6 +863,7 @@ class QInstanceValidatorTest
|
|||||||
possibleValueSource.setOrderByFields(List.of(new QFilterOrderBy("id")));
|
possibleValueSource.setOrderByFields(List.of(new QFilterOrderBy("id")));
|
||||||
possibleValueSource.setCustomCodeReference(null);
|
possibleValueSource.setCustomCodeReference(null);
|
||||||
possibleValueSource.setEnumValues(List.of(new QPossibleValue<>("test")));
|
possibleValueSource.setEnumValues(List.of(new QPossibleValue<>("test")));
|
||||||
|
possibleValueSource.setType(QPossibleValueSourceType.CUSTOM);
|
||||||
},
|
},
|
||||||
"should not have enum values",
|
"should not have enum values",
|
||||||
"should not have a tableName",
|
"should not have a tableName",
|
||||||
|
@ -2,6 +2,7 @@ qqq-backend-core
|
|||||||
qqq-backend-module-api
|
qqq-backend-module-api
|
||||||
qqq-backend-module-rdbms
|
qqq-backend-module-rdbms
|
||||||
qqq-backend-module-filesystem
|
qqq-backend-module-filesystem
|
||||||
|
qqq-language-support-javascript
|
||||||
qqq-middleware-javalin
|
qqq-middleware-javalin
|
||||||
qqq-middleware-picocli
|
qqq-middleware-picocli
|
||||||
qqq-middleware-lambda
|
qqq-middleware-lambda
|
||||||
|
@ -50,10 +50,10 @@ public class QJavaScriptExecutor implements QCodeExecutor
|
|||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@Override
|
@Override
|
||||||
public Serializable execute(QCodeReference codeReference, Map<String, Serializable> context, QCodeExecutionLoggerInterface executionLogger) throws QCodeException
|
public Serializable execute(QCodeReference codeReference, Map<String, Serializable> inputContext, QCodeExecutionLoggerInterface executionLogger) throws QCodeException
|
||||||
{
|
{
|
||||||
String code = getCode(codeReference);
|
String code = getCode(codeReference);
|
||||||
Serializable output = runInline(code, context, executionLogger);
|
Serializable output = runInline(code, inputContext, executionLogger);
|
||||||
return (output);
|
return (output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,13 +62,17 @@ public class QJavaScriptExecutor implements QCodeExecutor
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private Serializable runInline(String code, Map<String, Serializable> context, QCodeExecutionLoggerInterface executionLogger) throws QCodeException
|
private Serializable runInline(String code, Map<String, Serializable> inputContext, QCodeExecutionLoggerInterface executionLogger) throws QCodeException
|
||||||
{
|
{
|
||||||
new NashornScriptEngineFactory();
|
new NashornScriptEngineFactory();
|
||||||
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
|
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
|
||||||
|
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
// setup the javascript environment/context //
|
||||||
|
//////////////////////////////////////////////
|
||||||
Bindings bindings = engine.createBindings();
|
Bindings bindings = engine.createBindings();
|
||||||
bindings.putAll(context);
|
bindings.putAll(inputContext);
|
||||||
|
|
||||||
if(!bindings.containsKey("logger"))
|
if(!bindings.containsKey("logger"))
|
||||||
{
|
{
|
||||||
bindings.put("logger", executionLogger);
|
bindings.put("logger", executionLogger);
|
||||||
|
@ -135,7 +135,7 @@ public class TestUtils
|
|||||||
qInstance.addBackend(defineMemoryBackend());
|
qInstance.addBackend(defineMemoryBackend());
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
new ScriptsMetaDataProvider().defineStandardScriptsTables(qInstance, defineMemoryBackend().getName(), null);
|
new ScriptsMetaDataProvider().defineAll(qInstance, defineMemoryBackend().getName(), null);
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user