mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 21:20:45 +00:00
Merge branch 'feature/QQQ-28-bulk-ops-frontend' into feature/sprint-7-integration
This commit is contained in:
@ -52,7 +52,7 @@ public class AsyncJobCallback
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Update the message
|
||||
*******************************************************************************/
|
||||
public void updateStatus(String message)
|
||||
{
|
||||
@ -63,7 +63,20 @@ public class AsyncJobCallback
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Update all 3 status fields
|
||||
*******************************************************************************/
|
||||
public void updateStatus(String message, int current, int total)
|
||||
{
|
||||
this.asyncJobStatus.setMessage(message);
|
||||
this.asyncJobStatus.setCurrent(current);
|
||||
this.asyncJobStatus.setTotal(total);
|
||||
storeUpdatedStatus();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Update the current and total fields (e.g., 1 of 2, 2 of 2, 3 of 2)
|
||||
*******************************************************************************/
|
||||
public void updateStatus(int current, int total)
|
||||
{
|
||||
@ -75,13 +88,12 @@ public class AsyncJobCallback
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Remove the values from the current & total fields
|
||||
*******************************************************************************/
|
||||
public void updateStatus(String message, int current, int total)
|
||||
public void clearCurrentAndTotal()
|
||||
{
|
||||
this.asyncJobStatus.setMessage(message);
|
||||
this.asyncJobStatus.setCurrent(current);
|
||||
this.asyncJobStatus.setTotal(total);
|
||||
this.asyncJobStatus.setCurrent(null);
|
||||
this.asyncJobStatus.setTotal(null);
|
||||
storeUpdatedStatus();
|
||||
}
|
||||
|
||||
|
@ -37,4 +37,17 @@ public interface DeleteInterface
|
||||
**
|
||||
*******************************************************************************/
|
||||
DeleteOutput execute(DeleteInput deleteInput) throws QException;
|
||||
|
||||
/*******************************************************************************
|
||||
** Specify whether this particular module's delete action natively supports
|
||||
** receiving a queryFilter as input (e.g., SQL does). If the module doesn't
|
||||
** support a query filter, then the qqq framework (DeleteAction) will, if it
|
||||
** receives a queryFilter in its input, it will execute the query, and pass
|
||||
** the list of primary keys down into the module's delete implementation.
|
||||
*******************************************************************************/
|
||||
default boolean supportsQueryFilterInput()
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ public class RunProcessAction
|
||||
///////////////////////
|
||||
// Run backend steps //
|
||||
///////////////////////
|
||||
runBackendStep(runProcessInput, process, runProcessOutput, stateKey, backendStepMetaData, processState);
|
||||
runBackendStep(runProcessInput, process, runProcessOutput, stateKey, backendStepMetaData, process, processState);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -225,11 +225,12 @@ public class RunProcessAction
|
||||
/*******************************************************************************
|
||||
** Run a single backend step.
|
||||
*******************************************************************************/
|
||||
private void runBackendStep(RunProcessInput runProcessInput, QProcessMetaData process, RunProcessOutput runProcessOutput, UUIDAndTypeStateKey stateKey, QBackendStepMetaData backendStep, ProcessState processState) throws Exception
|
||||
private void runBackendStep(RunProcessInput runProcessInput, QProcessMetaData process, RunProcessOutput runProcessOutput, UUIDAndTypeStateKey stateKey, QBackendStepMetaData backendStep, QProcessMetaData qProcessMetaData, ProcessState processState) throws Exception
|
||||
{
|
||||
RunBackendStepInput runBackendStepInput = new RunBackendStepInput(runProcessInput.getInstance(), processState);
|
||||
runBackendStepInput.setProcessName(process.getName());
|
||||
runBackendStepInput.setStepName(backendStep.getName());
|
||||
runBackendStepInput.setTableName(process.getTableName());
|
||||
runBackendStepInput.setSession(runProcessInput.getSession());
|
||||
runBackendStepInput.setCallback(runProcessInput.getCallback());
|
||||
runBackendStepInput.setAsyncJobCallback(runProcessInput.getAsyncJobCallback());
|
||||
|
@ -22,12 +22,21 @@
|
||||
package com.kingsrook.qqq.backend.core.actions.tables;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||
import com.kingsrook.qqq.backend.core.actions.interfaces.DeleteInterface;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteOutput;
|
||||
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.modules.backend.QBackendModuleDispatcher;
|
||||
import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -36,6 +45,10 @@ import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface;
|
||||
*******************************************************************************/
|
||||
public class DeleteAction
|
||||
{
|
||||
private static final Logger LOG = LogManager.getLogger(DeleteAction.class);
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@ -44,10 +57,64 @@ public class DeleteAction
|
||||
ActionHelper.validateSession(deleteInput);
|
||||
|
||||
QBackendModuleDispatcher qBackendModuleDispatcher = new QBackendModuleDispatcher();
|
||||
QBackendModuleInterface qModule = qBackendModuleDispatcher.getQBackendModule(deleteInput.getBackend());
|
||||
QBackendModuleInterface qModule = qBackendModuleDispatcher.getQBackendModule(deleteInput.getBackend());
|
||||
// todo pre-customization - just get to modify the request?
|
||||
DeleteOutput deleteResult = qModule.getDeleteInterface().execute(deleteInput);
|
||||
|
||||
if(CollectionUtils.nullSafeHasContents(deleteInput.getPrimaryKeys()) && deleteInput.getQueryFilter() != null)
|
||||
{
|
||||
throw (new QException("A delete request may not contain both a list of primary keys and a query filter."));
|
||||
}
|
||||
|
||||
DeleteInterface deleteInterface = qModule.getDeleteInterface();
|
||||
if(deleteInput.getQueryFilter() != null && !deleteInterface.supportsQueryFilterInput())
|
||||
{
|
||||
LOG.info("Querying for primary keys, for backend module " + qModule.getBackendType() + " which does not support queryFilter input for deletes");
|
||||
List<Serializable> primaryKeyList = getPrimaryKeysFromQueryFilter(deleteInput);
|
||||
deleteInput.setPrimaryKeys(primaryKeyList);
|
||||
|
||||
if(primaryKeyList.isEmpty())
|
||||
{
|
||||
LOG.info("0 primaryKeys found. Returning with no-op");
|
||||
DeleteOutput deleteOutput = new DeleteOutput();
|
||||
deleteOutput.setRecordsWithErrors(new ArrayList<>());
|
||||
return (deleteOutput);
|
||||
}
|
||||
}
|
||||
|
||||
DeleteOutput deleteResult = deleteInterface.execute(deleteInput);
|
||||
// todo post-customization - can do whatever w/ the result if you want
|
||||
|
||||
return deleteResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** For an implementation that doesn't support a queryFilter as its input,
|
||||
** but a scenario where a query filter was passed in - run the query, to
|
||||
** get a list of primary keys.
|
||||
*******************************************************************************/
|
||||
public static List<Serializable> getPrimaryKeysFromQueryFilter(DeleteInput deleteInput) throws QException
|
||||
{
|
||||
try
|
||||
{
|
||||
QBackendModuleDispatcher qBackendModuleDispatcher = new QBackendModuleDispatcher();
|
||||
QBackendModuleInterface qModule = qBackendModuleDispatcher.getQBackendModule(deleteInput.getBackend());
|
||||
|
||||
QueryInput queryInput = new QueryInput(deleteInput.getInstance(), deleteInput.getSession());
|
||||
queryInput.setTableName(deleteInput.getTableName());
|
||||
queryInput.setFilter(deleteInput.getQueryFilter());
|
||||
QueryOutput queryOutput = qModule.getQueryInterface().execute(queryInput);
|
||||
|
||||
return (queryOutput.getRecords().stream()
|
||||
.map(r -> r.getValue(deleteInput.getTable().getPrimaryKeyField()))
|
||||
.toList());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
LOG.warn("Error getting primary keys from query filter before bulk-delete", e);
|
||||
throw (new QException("Error getting keys from filter prior to delete.", e));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,14 +22,31 @@
|
||||
package com.kingsrook.qqq.backend.core.instances;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QComponentType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendComponentMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionOutputMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QRecordListMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.bulk.delete.BulkDeleteStoreStep;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.bulk.edit.BulkEditReceiveValuesStep;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.bulk.edit.BulkEditStoreRecordsStep;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.BulkInsertReceiveFileStep;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.bulk.insert.BulkInsertStoreRecordsStep;
|
||||
import com.kingsrook.qqq.backend.core.processes.implementations.general.LoadInitialRecordsStep;
|
||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||
|
||||
|
||||
@ -48,6 +65,7 @@ public class QInstanceEnricher
|
||||
if(qInstance.getTables() != null)
|
||||
{
|
||||
qInstance.getTables().values().forEach(this::enrich);
|
||||
defineTableBulkProcesses(qInstance);
|
||||
}
|
||||
|
||||
if(qInstance.getProcesses() != null)
|
||||
@ -122,7 +140,7 @@ public class QInstanceEnricher
|
||||
step.getInputFields().forEach(this::enrich);
|
||||
step.getOutputFields().forEach(this::enrich);
|
||||
|
||||
if (step instanceof QFrontendStepMetaData frontendStepMetaData)
|
||||
if(step instanceof QFrontendStepMetaData frontendStepMetaData)
|
||||
{
|
||||
if(frontendStepMetaData.getFormFields() != null)
|
||||
{
|
||||
@ -167,4 +185,229 @@ public class QInstanceEnricher
|
||||
return (name.substring(0, 1).toUpperCase(Locale.ROOT) + name.substring(1).replaceAll("([A-Z])", " $1"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Add bulk insert/edit/delete processes to all tables (unless the meta data
|
||||
** already had these processes defined (e.g., the user defined custom ones)
|
||||
*******************************************************************************/
|
||||
private void defineTableBulkProcesses(QInstance qInstance)
|
||||
{
|
||||
for(QTableMetaData table : qInstance.getTables().values())
|
||||
{
|
||||
if(table.getFields() == null)
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// these processes can't be defined if there aren't any fields //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
continue;
|
||||
}
|
||||
|
||||
// todo - add idea of 'supportsBulkX'
|
||||
String bulkInsertProcessName = table.getName() + ".bulkInsert";
|
||||
if(qInstance.getProcess(bulkInsertProcessName) == null)
|
||||
{
|
||||
defineTableBulkInsert(qInstance, table, bulkInsertProcessName);
|
||||
}
|
||||
|
||||
String bulkEditProcessName = table.getName() + ".bulkEdit";
|
||||
if(qInstance.getProcess(bulkEditProcessName) == null)
|
||||
{
|
||||
defineTableBulkEdit(qInstance, table, bulkEditProcessName);
|
||||
}
|
||||
|
||||
String bulkDeleteProcessName = table.getName() + ".bulkDelete";
|
||||
if(qInstance.getProcess(bulkDeleteProcessName) == null)
|
||||
{
|
||||
defineTableBulkDelete(qInstance, table, bulkDeleteProcessName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void defineTableBulkInsert(QInstance qInstance, QTableMetaData table, String processName)
|
||||
{
|
||||
List<QFieldMetaData> editableFields = table.getFields().values().stream()
|
||||
.filter(QFieldMetaData::getIsEditable)
|
||||
.toList();
|
||||
|
||||
String fieldsForHelpText = editableFields.stream()
|
||||
.map(QFieldMetaData::getLabel)
|
||||
.collect(Collectors.joining(", "));
|
||||
|
||||
QFrontendStepMetaData uploadScreen = new QFrontendStepMetaData()
|
||||
.withName("upload")
|
||||
.withLabel("Upload File")
|
||||
.withFormField(new QFieldMetaData("theFile", QFieldType.BLOB).withIsRequired(true))
|
||||
.withComponent(new QFrontendComponentMetaData()
|
||||
.withType(QComponentType.HELP_TEXT)
|
||||
.withValue("text", "Upload a CSV or XLSX file with the following columns: " + fieldsForHelpText));
|
||||
|
||||
QBackendStepMetaData receiveFileStep = new QBackendStepMetaData()
|
||||
.withName("receiveFile")
|
||||
.withCode(new QCodeReference(BulkInsertReceiveFileStep.class))
|
||||
.withInputData(new QFunctionInputMetaData()
|
||||
// todo - our upload file as a field? problem is, its type...
|
||||
.withFieldList(List.of()))
|
||||
.withOutputMetaData(new QFunctionOutputMetaData()
|
||||
.withFieldList(List.of(new QFieldMetaData("noOfFileRows", QFieldType.INTEGER))));
|
||||
|
||||
QFrontendStepMetaData reviewScreen = new QFrontendStepMetaData()
|
||||
.withName("review")
|
||||
.withRecordListFields(editableFields)
|
||||
.withComponent(new QFrontendComponentMetaData()
|
||||
.withType(QComponentType.HELP_TEXT)
|
||||
.withValue("text", "The records below were parsed from your file, and will be inserted if you click Submit."))
|
||||
.withViewField(new QFieldMetaData("noOfFileRows", QFieldType.INTEGER).withLabel("# of file rows"));
|
||||
|
||||
QBackendStepMetaData storeStep = new QBackendStepMetaData()
|
||||
.withName("storeRecords")
|
||||
.withCode(new QCodeReference(BulkInsertStoreRecordsStep.class))
|
||||
.withInputData(new QFunctionInputMetaData()
|
||||
// todo - our upload file as a field? problem is, its type...
|
||||
.withFieldList(List.of()))
|
||||
.withOutputMetaData(new QFunctionOutputMetaData()
|
||||
.withFieldList(List.of(new QFieldMetaData("noOfFileRows", QFieldType.INTEGER))));
|
||||
|
||||
QFrontendStepMetaData resultsScreen = new QFrontendStepMetaData()
|
||||
.withName("results")
|
||||
.withRecordListFields(new ArrayList<>(table.getFields().values()))
|
||||
.withComponent(new QFrontendComponentMetaData()
|
||||
.withType(QComponentType.HELP_TEXT)
|
||||
.withValue("text", "The records below have been inserted."))
|
||||
.withViewField(new QFieldMetaData("noOfFileRows", QFieldType.INTEGER).withLabel("# of file rows"));
|
||||
|
||||
qInstance.addProcess(
|
||||
new QProcessMetaData()
|
||||
.withName(processName)
|
||||
.withLabel(table.getLabel() + " Bulk Insert")
|
||||
.withTableName(table.getName())
|
||||
.withIsHidden(true)
|
||||
.withStepList(List.of(
|
||||
uploadScreen,
|
||||
receiveFileStep,
|
||||
reviewScreen,
|
||||
storeStep,
|
||||
resultsScreen
|
||||
)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void defineTableBulkEdit(QInstance qInstance, QTableMetaData table, String processName)
|
||||
{
|
||||
List<QFieldMetaData> editableFields = table.getFields().values().stream()
|
||||
.filter(QFieldMetaData::getIsEditable)
|
||||
.toList();
|
||||
|
||||
QFrontendStepMetaData editScreen = new QFrontendStepMetaData()
|
||||
.withName("edit")
|
||||
.withLabel("Edit Values")
|
||||
.withFormFields(editableFields)
|
||||
.withComponent(new QFrontendComponentMetaData()
|
||||
.withType(QComponentType.HELP_TEXT)
|
||||
.withValue("text", """
|
||||
Flip the switches next to the fields that you want to edit.
|
||||
The values you supply here will be updated in all of the records you are bulk editing.
|
||||
You can clear out the value in a field by flipping the switch on for that field and leaving the input field blank.
|
||||
Fields whose switches are off will not be updated."""))
|
||||
.withComponent(new QFrontendComponentMetaData()
|
||||
.withType(QComponentType.BULK_EDIT_FORM)
|
||||
);
|
||||
|
||||
QBackendStepMetaData receiveValuesStep = new QBackendStepMetaData()
|
||||
.withName("receiveValues")
|
||||
.withCode(new QCodeReference(BulkEditReceiveValuesStep.class))
|
||||
.withInputData(new QFunctionInputMetaData()
|
||||
.withRecordListMetaData(new QRecordListMetaData().withTableName(table.getName()))
|
||||
.withField(new QFieldMetaData(BulkEditReceiveValuesStep.FIELD_ENABLED_FIELDS, QFieldType.STRING))
|
||||
.withFields(editableFields));
|
||||
|
||||
QFrontendStepMetaData reviewScreen = new QFrontendStepMetaData()
|
||||
.withName("review")
|
||||
.withRecordListFields(editableFields)
|
||||
.withViewField(new QFieldMetaData(BulkEditReceiveValuesStep.FIELD_VALUES_BEING_UPDATED, QFieldType.STRING))
|
||||
.withComponent(new QFrontendComponentMetaData()
|
||||
.withType(QComponentType.HELP_TEXT)
|
||||
.withValue("text", "The records below will be updated if you click Submit."));
|
||||
|
||||
QBackendStepMetaData storeStep = new QBackendStepMetaData()
|
||||
.withName("storeRecords")
|
||||
.withCode(new QCodeReference(BulkEditStoreRecordsStep.class))
|
||||
.withInputData(new QFunctionInputMetaData()
|
||||
// todo - our upload file as a field? problem is, its type...
|
||||
.withFieldList(List.of()))
|
||||
.withOutputMetaData(new QFunctionOutputMetaData()
|
||||
.withFieldList(List.of(new QFieldMetaData("noOfFileRows", QFieldType.INTEGER))));
|
||||
|
||||
QFrontendStepMetaData resultsScreen = new QFrontendStepMetaData()
|
||||
.withName("results")
|
||||
.withRecordListFields(new ArrayList<>(table.getFields().values()))
|
||||
.withComponent(new QFrontendComponentMetaData()
|
||||
.withType(QComponentType.HELP_TEXT)
|
||||
.withValue("text", "The records below have been updated."));
|
||||
|
||||
qInstance.addProcess(
|
||||
new QProcessMetaData()
|
||||
.withName(processName)
|
||||
.withLabel(table.getLabel() + " Bulk Edit")
|
||||
.withTableName(table.getName())
|
||||
.withIsHidden(true)
|
||||
.withStepList(List.of(
|
||||
LoadInitialRecordsStep.defineMetaData(table.getName()),
|
||||
editScreen,
|
||||
receiveValuesStep,
|
||||
reviewScreen,
|
||||
storeStep,
|
||||
resultsScreen
|
||||
)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void defineTableBulkDelete(QInstance qInstance, QTableMetaData table, String processName)
|
||||
{
|
||||
QFrontendStepMetaData reviewScreen = new QFrontendStepMetaData()
|
||||
.withName("review")
|
||||
.withRecordListFields(new ArrayList<>(table.getFields().values()))
|
||||
.withComponent(new QFrontendComponentMetaData()
|
||||
.withType(QComponentType.HELP_TEXT)
|
||||
.withValue("text", "The records below will be deleted if you click Submit."));
|
||||
|
||||
QBackendStepMetaData storeStep = new QBackendStepMetaData()
|
||||
.withName("delete")
|
||||
.withCode(new QCodeReference(BulkDeleteStoreStep.class));
|
||||
|
||||
QFrontendStepMetaData resultsScreen = new QFrontendStepMetaData()
|
||||
.withName("results")
|
||||
.withRecordListFields(new ArrayList<>(table.getFields().values()))
|
||||
.withComponent(new QFrontendComponentMetaData()
|
||||
.withType(QComponentType.HELP_TEXT)
|
||||
.withValue("text", "The records below have been deleted."));
|
||||
|
||||
qInstance.addProcess(
|
||||
new QProcessMetaData()
|
||||
.withName(processName)
|
||||
.withLabel(table.getLabel() + " Bulk Delete")
|
||||
.withTableName(table.getName())
|
||||
.withIsHidden(true)
|
||||
.withStepList(List.of(
|
||||
LoadInitialRecordsStep.defineMetaData(table.getName()),
|
||||
reviewScreen,
|
||||
storeStep,
|
||||
resultsScreen
|
||||
)));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,9 @@
|
||||
package com.kingsrook.qqq.backend.core.model.actions;
|
||||
|
||||
|
||||
import java.util.UUID;
|
||||
import com.kingsrook.qqq.backend.core.actions.async.AsyncJobCallback;
|
||||
import com.kingsrook.qqq.backend.core.actions.async.AsyncJobStatus;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
||||
import com.kingsrook.qqq.backend.core.instances.QInstanceValidator;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationMetaData;
|
||||
@ -40,7 +43,9 @@ public abstract class AbstractActionInput
|
||||
private static final Logger LOG = LogManager.getLogger(AbstractActionInput.class);
|
||||
|
||||
protected QInstance instance;
|
||||
protected QSession session;
|
||||
protected QSession session;
|
||||
|
||||
private AsyncJobCallback asyncJobCallback;
|
||||
|
||||
|
||||
|
||||
@ -59,7 +64,16 @@ public abstract class AbstractActionInput
|
||||
public AbstractActionInput(QInstance instance)
|
||||
{
|
||||
this.instance = instance;
|
||||
validateInstance(instance);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** performance instance validation (if not previously done).
|
||||
*******************************************************************************/
|
||||
private void validateInstance(QInstance instance)
|
||||
{
|
||||
////////////////////////////////////////////////////////////
|
||||
// if this instance hasn't been validated yet, do so now //
|
||||
// noting that this will also enrich any missing metaData //
|
||||
@ -107,6 +121,7 @@ public abstract class AbstractActionInput
|
||||
*******************************************************************************/
|
||||
public void setInstance(QInstance instance)
|
||||
{
|
||||
validateInstance(instance);
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
@ -131,4 +146,33 @@ public abstract class AbstractActionInput
|
||||
{
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for asyncJobCallback
|
||||
**
|
||||
*******************************************************************************/
|
||||
public AsyncJobCallback getAsyncJobCallback()
|
||||
{
|
||||
if(asyncJobCallback == null)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// don't return null here (too easy to NPE). instead, if someone wants one of these, create one and give it to them. //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
asyncJobCallback = new AsyncJobCallback(UUID.randomUUID(), new AsyncJobStatus());
|
||||
}
|
||||
return asyncJobCallback;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for asyncJobCallback
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setAsyncJobCallback(AsyncJobCallback asyncJobCallback)
|
||||
{
|
||||
this.asyncJobCallback = asyncJobCallback;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.actions.processes;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Model a file that a user uploaded (or otherwise submitted to the qqq backend).
|
||||
*******************************************************************************/
|
||||
public class QUploadedFile implements Serializable
|
||||
{
|
||||
private String filename;
|
||||
private byte[] bytes;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for filename
|
||||
**
|
||||
*******************************************************************************/
|
||||
public String getFilename()
|
||||
{
|
||||
return filename;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for filename
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setFilename(String filename)
|
||||
{
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for bytes
|
||||
**
|
||||
*******************************************************************************/
|
||||
public byte[] getBytes()
|
||||
{
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for bytes
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setBytes(byte[] bytes)
|
||||
{
|
||||
this.bytes = bytes;
|
||||
}
|
||||
}
|
@ -33,6 +33,7 @@ import com.kingsrook.qqq.backend.core.model.actions.AbstractActionInput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||
|
||||
|
||||
@ -44,6 +45,7 @@ public class RunBackendStepInput extends AbstractActionInput
|
||||
{
|
||||
private ProcessState processState;
|
||||
private String processName;
|
||||
private String tableName;
|
||||
private String stepName;
|
||||
private QProcessCallback callback;
|
||||
private AsyncJobCallback asyncJobCallback;
|
||||
@ -126,6 +128,55 @@ public class RunBackendStepInput extends AbstractActionInput
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for tableName
|
||||
**
|
||||
*******************************************************************************/
|
||||
public String getTableName()
|
||||
{
|
||||
return tableName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for tableName
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setTableName(String tableName)
|
||||
{
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for tableName
|
||||
**
|
||||
*******************************************************************************/
|
||||
public RunBackendStepInput withTableName(String tableName)
|
||||
{
|
||||
this.tableName = tableName;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QTableMetaData getTable()
|
||||
{
|
||||
if(tableName == null)
|
||||
{
|
||||
return (null);
|
||||
}
|
||||
|
||||
return (instance.getTable(tableName));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for functionName
|
||||
**
|
||||
@ -334,7 +385,7 @@ public class RunBackendStepInput extends AbstractActionInput
|
||||
*******************************************************************************/
|
||||
public AsyncJobCallback getAsyncJobCallback()
|
||||
{
|
||||
if (asyncJobCallback == null)
|
||||
if(asyncJobCallback == null)
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// avoid NPE in case we didn't have one of these! create a new one... //
|
||||
|
@ -27,6 +27,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -183,4 +184,38 @@ public class RunBackendStepOutput extends AbstractActionOutput
|
||||
{
|
||||
return exception;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for a single field's value
|
||||
**
|
||||
*******************************************************************************/
|
||||
public Serializable getValue(String fieldName)
|
||||
{
|
||||
return (processState.getValues().get(fieldName));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for a single field's value
|
||||
**
|
||||
*******************************************************************************/
|
||||
public String getValueString(String fieldName)
|
||||
{
|
||||
return ((String) getValue(fieldName));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for a single field's value
|
||||
**
|
||||
*******************************************************************************/
|
||||
public Integer getValueInteger(String fieldName)
|
||||
{
|
||||
return (ValueUtils.getValueAsInteger(getValue(fieldName)));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ package com.kingsrook.qqq.backend.core.model.actions.tables.delete;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractTableActionInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
|
||||
|
||||
@ -35,6 +36,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
public class DeleteInput extends AbstractTableActionInput
|
||||
{
|
||||
private List<Serializable> primaryKeys;
|
||||
private QQueryFilter queryFilter;
|
||||
|
||||
|
||||
|
||||
@ -88,4 +90,37 @@ public class DeleteInput extends AbstractTableActionInput
|
||||
this.primaryKeys = primaryKeys;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for queryFilter
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QQueryFilter getQueryFilter()
|
||||
{
|
||||
return queryFilter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for queryFilter
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setQueryFilter(QQueryFilter queryFilter)
|
||||
{
|
||||
this.queryFilter = queryFilter;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for queryFilter
|
||||
**
|
||||
*******************************************************************************/
|
||||
public DeleteInput withQueryFilter(QQueryFilter queryFilter)
|
||||
{
|
||||
this.queryFilter = queryFilter;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,6 +22,8 @@
|
||||
package com.kingsrook.qqq.backend.core.model.actions.tables.delete;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
@ -31,18 +33,31 @@ import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
* Output for a delete action
|
||||
*
|
||||
*******************************************************************************/
|
||||
public class DeleteOutput extends AbstractActionOutput
|
||||
public class DeleteOutput extends AbstractActionOutput implements Serializable
|
||||
{
|
||||
private List<QRecord> records;
|
||||
private int deletedRecordCount = 0;
|
||||
private List<QRecord> recordsWithErrors;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for deletedRecordCount
|
||||
**
|
||||
*******************************************************************************/
|
||||
public List<QRecord> getRecords()
|
||||
public int getDeletedRecordCount()
|
||||
{
|
||||
return records;
|
||||
return deletedRecordCount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for deletedRecordCount
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setDeletedRecordCount(int deletedRecordCount)
|
||||
{
|
||||
this.deletedRecordCount = deletedRecordCount;
|
||||
}
|
||||
|
||||
|
||||
@ -50,8 +65,40 @@ public class DeleteOutput extends AbstractActionOutput
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setRecords(List<QRecord> records)
|
||||
public List<QRecord> getRecordsWithErrors()
|
||||
{
|
||||
this.records = records;
|
||||
return recordsWithErrors;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setRecordsWithErrors(List<QRecord> recordsWithErrors)
|
||||
{
|
||||
this.recordsWithErrors = recordsWithErrors;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void addRecordWithError(QRecord recordWithError)
|
||||
{
|
||||
if(this.recordsWithErrors == null)
|
||||
{
|
||||
this.recordsWithErrors = new ArrayList<>();
|
||||
}
|
||||
this.recordsWithErrors.add(recordWithError);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void addToDeletedRecordCount(int i)
|
||||
{
|
||||
deletedRecordCount += i;
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ import java.util.List;
|
||||
* A single criteria Component of a Query
|
||||
*
|
||||
*******************************************************************************/
|
||||
public class QFilterCriteria
|
||||
public class QFilterCriteria implements Serializable
|
||||
{
|
||||
private String fieldName;
|
||||
private QCriteriaOperator operator;
|
||||
|
@ -22,11 +22,14 @@
|
||||
package com.kingsrook.qqq.backend.core.model.actions.tables.query;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Bean representing an element of a query order-by clause.
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class QFilterOrderBy
|
||||
public class QFilterOrderBy implements Serializable
|
||||
{
|
||||
private String fieldName;
|
||||
private boolean isAscending = true;
|
||||
|
@ -22,6 +22,7 @@
|
||||
package com.kingsrook.qqq.backend.core.model.actions.tables.query;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -30,7 +31,7 @@ import java.util.List;
|
||||
* Full "filter" for a query - a list of criteria and order-bys
|
||||
*
|
||||
*******************************************************************************/
|
||||
public class QQueryFilter
|
||||
public class QQueryFilter implements Serializable
|
||||
{
|
||||
private List<QFilterCriteria> criteria = new ArrayList<>();
|
||||
private List<QFilterOrderBy> orderBys = new ArrayList<>();
|
||||
|
@ -25,6 +25,7 @@ package com.kingsrook.qqq.backend.core.model.actions.tables.query;
|
||||
import com.kingsrook.qqq.backend.core.actions.reporting.RecordPipe;
|
||||
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.session.QSession;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -60,6 +61,17 @@ public class QueryInput extends AbstractTableActionInput
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QueryInput(QInstance instance, QSession session)
|
||||
{
|
||||
super(instance);
|
||||
setSession(session);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for filter
|
||||
**
|
||||
|
@ -36,6 +36,14 @@ public class UpdateInput extends AbstractTableActionInput
|
||||
{
|
||||
private List<QRecord> records;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// allow a caller to specify that they KNOW this optimization (e.g., in SQL) can be made. //
|
||||
// If you set this to true, but it isn't, then you may not get an accurate update. //
|
||||
// If you set this to false, but it isn't, then you may not get the best performance. //
|
||||
// Just leave it null if you don't know what you're dong. //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
private Boolean areAllValuesBeingUpdatedTheSame = null;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -76,4 +84,27 @@ public class UpdateInput extends AbstractTableActionInput
|
||||
{
|
||||
this.records = records;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for areAllValuesBeingUpdatedTheSame
|
||||
**
|
||||
*******************************************************************************/
|
||||
public Boolean getAreAllValuesBeingUpdatedTheSame()
|
||||
{
|
||||
return areAllValuesBeingUpdatedTheSame;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for areAllValuesBeingUpdatedTheSame
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setAreAllValuesBeingUpdatedTheSame(Boolean areAllValuesBeingUpdatedTheSame)
|
||||
{
|
||||
this.areAllValuesBeingUpdatedTheSame = areAllValuesBeingUpdatedTheSame;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,9 +25,12 @@ package com.kingsrook.qqq.backend.core.model.data;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||
|
||||
|
||||
@ -54,7 +57,7 @@ public class QRecord implements Serializable
|
||||
private Map<String, Serializable> values = new LinkedHashMap<>();
|
||||
private Map<String, String> displayValues = new LinkedHashMap<>();
|
||||
private Map<String, Serializable> backendDetails = new LinkedHashMap<>();
|
||||
// todo private List<String> errors = new ArrayList<>();
|
||||
private List<String> errors = new ArrayList<>();
|
||||
|
||||
|
||||
|
||||
@ -66,6 +69,16 @@ public class QRecord implements Serializable
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QRecord(QTableMetaData tableMetaData, Serializable primaryKeyValue)
|
||||
{
|
||||
setTableName(tableMetaData.getName());
|
||||
setValue(tableMetaData.getPrimaryKeyField(), primaryKeyValue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Copy constructor.
|
||||
@ -77,7 +90,7 @@ public class QRecord implements Serializable
|
||||
this.values = record.values;
|
||||
this.displayValues = record.displayValues;
|
||||
this.backendDetails = record.backendDetails;
|
||||
// todo! this.errors = record.errors;
|
||||
this.errors = record.errors;
|
||||
}
|
||||
|
||||
|
||||
@ -344,6 +357,49 @@ public class QRecord implements Serializable
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for errors
|
||||
**
|
||||
*******************************************************************************/
|
||||
public List<String> getErrors()
|
||||
{
|
||||
return (errors);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for errors
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setErrors(List<String> errors)
|
||||
{
|
||||
this.errors = errors;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Add one error to this record
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void addError(String error)
|
||||
{
|
||||
this.errors.add(error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluently Add one error to this record
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QRecord withError(String error)
|
||||
{
|
||||
addError(error);
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Convert this record to an QRecordEntity
|
||||
@ -352,4 +408,5 @@ public class QRecord implements Serializable
|
||||
{
|
||||
return (QRecordEntity.fromQRecord(c, this));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,17 +22,74 @@
|
||||
package com.kingsrook.qqq.backend.core.model.metadata.code;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Pointer to code to be ran by the qqq framework, e.g., for custom behavior -
|
||||
** maybe process steps, maybe customization to a table, etc.
|
||||
*******************************************************************************/
|
||||
public class QCodeReference
|
||||
{
|
||||
private String name;
|
||||
private QCodeType codeType;
|
||||
private String name;
|
||||
private QCodeType codeType;
|
||||
private QCodeUsage codeUsage;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Default empty constructor
|
||||
*******************************************************************************/
|
||||
public QCodeReference()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor that takes all args
|
||||
*******************************************************************************/
|
||||
public QCodeReference(String name, QCodeType codeType, QCodeUsage codeUsage)
|
||||
{
|
||||
this.name = name;
|
||||
this.codeType = codeType;
|
||||
this.codeUsage = codeUsage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor that just takes a java class, and infers the other fields.
|
||||
*******************************************************************************/
|
||||
public QCodeReference(Class<?> javaClass)
|
||||
{
|
||||
this.name = javaClass.getName();
|
||||
this.codeType = QCodeType.JAVA;
|
||||
|
||||
if(BackendStep.class.isAssignableFrom(javaClass))
|
||||
{
|
||||
this.codeUsage = QCodeUsage.BACKEND_STEP;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw (new IllegalStateException("Unable to infer code usage type for class: " + javaClass.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor that just takes a java class and code usage.
|
||||
*******************************************************************************/
|
||||
public QCodeReference(Class<?> javaClass, QCodeUsage codeUsage)
|
||||
{
|
||||
this.name = javaClass.getName();
|
||||
this.codeType = QCodeType.JAVA;
|
||||
this.codeUsage = codeUsage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for name
|
||||
**
|
||||
|
@ -40,6 +40,12 @@ public class QFieldMetaData
|
||||
private String backendName;
|
||||
private QFieldType type;
|
||||
private boolean isRequired = false;
|
||||
private boolean isEditable = true;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// if we need "only edit on insert" or "only edit on update" in the future, //
|
||||
// propose doing that in a secondary field, e.g., "onlyEditableOn=insert|update" //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private Serializable defaultValue;
|
||||
private String possibleValueSourceName;
|
||||
@ -315,4 +321,37 @@ public class QFieldMetaData
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for isEditable
|
||||
**
|
||||
*******************************************************************************/
|
||||
public boolean getIsEditable()
|
||||
{
|
||||
return isEditable;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for isEditable
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setIsEditable(boolean isEditable)
|
||||
{
|
||||
this.isEditable = isEditable;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QFieldMetaData withIsEditable(boolean isEditable)
|
||||
{
|
||||
this.isEditable = isEditable;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -40,7 +40,8 @@ public enum QFieldType
|
||||
DATE_TIME,
|
||||
TEXT,
|
||||
HTML,
|
||||
PASSWORD;
|
||||
PASSWORD,
|
||||
BLOB;
|
||||
|
||||
|
||||
|
||||
|
@ -40,6 +40,7 @@ public class QFrontendFieldMetaData
|
||||
private String label;
|
||||
private QFieldType type;
|
||||
private boolean isRequired;
|
||||
private boolean isEditable;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// do not add setters. take values from the source-object in the constructor!! //
|
||||
@ -48,7 +49,7 @@ public class QFrontendFieldMetaData
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Constructor
|
||||
*******************************************************************************/
|
||||
public QFrontendFieldMetaData(QFieldMetaData fieldMetaData)
|
||||
{
|
||||
@ -56,6 +57,7 @@ public class QFrontendFieldMetaData
|
||||
this.label = fieldMetaData.getLabel();
|
||||
this.type = fieldMetaData.getType();
|
||||
this.isRequired = fieldMetaData.getIsRequired();
|
||||
this.isEditable = fieldMetaData.getIsEditable();
|
||||
}
|
||||
|
||||
|
||||
@ -101,4 +103,16 @@ public class QFrontendFieldMetaData
|
||||
{
|
||||
return isRequired;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for isEditable
|
||||
**
|
||||
*******************************************************************************/
|
||||
public boolean getIsEditable()
|
||||
{
|
||||
return isEditable;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.processes;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Types of UI Components that can be specified in frontend process steps.
|
||||
*******************************************************************************/
|
||||
public enum QComponentType
|
||||
{
|
||||
HELP_TEXT,
|
||||
BULK_EDIT_FORM;
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// keep these values in sync with QComponentType.ts in qqq-frontend-core //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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.processes;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Definition of a UI component in a frontend process steps.
|
||||
*******************************************************************************/
|
||||
public class QFrontendComponentMetaData
|
||||
{
|
||||
private QComponentType type;
|
||||
|
||||
private Map<String, Serializable> values;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for type
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QComponentType getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for type
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setType(QComponentType type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for type
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QFrontendComponentMetaData withType(QComponentType type)
|
||||
{
|
||||
this.type = type;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for values
|
||||
**
|
||||
*******************************************************************************/
|
||||
public Map<String, Serializable> getValues()
|
||||
{
|
||||
return values;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for values
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setValues(Map<String, Serializable> values)
|
||||
{
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for values
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QFrontendComponentMetaData withValues(Map<String, Serializable> values)
|
||||
{
|
||||
this.values = values;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for values
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QFrontendComponentMetaData withValue(String key, Serializable value)
|
||||
{
|
||||
if(values == null)
|
||||
{
|
||||
values = new HashMap<>();
|
||||
}
|
||||
values.put(key, value);
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
@ -34,9 +34,10 @@ import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
*******************************************************************************/
|
||||
public class QFrontendStepMetaData extends QStepMetaData
|
||||
{
|
||||
private List<QFieldMetaData> formFields;
|
||||
private List<QFieldMetaData> viewFields;
|
||||
private List<QFieldMetaData> recordListFields;
|
||||
private List<QFrontendComponentMetaData> components;
|
||||
private List<QFieldMetaData> formFields;
|
||||
private List<QFieldMetaData> viewFields;
|
||||
private List<QFieldMetaData> recordListFields;
|
||||
|
||||
|
||||
|
||||
@ -50,6 +51,56 @@ public class QFrontendStepMetaData extends QStepMetaData
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for components
|
||||
**
|
||||
*******************************************************************************/
|
||||
public List<QFrontendComponentMetaData> getComponents()
|
||||
{
|
||||
return components;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for components
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void setComponents(List<QFrontendComponentMetaData> components)
|
||||
{
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for adding 1 component
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QFrontendStepMetaData withComponent(QFrontendComponentMetaData component)
|
||||
{
|
||||
if(this.components == null)
|
||||
{
|
||||
this.components = new ArrayList<>();
|
||||
}
|
||||
this.components.add(component);
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for components
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QFrontendStepMetaData withComponents(List<QFrontendComponentMetaData> components)
|
||||
{
|
||||
this.components = components;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for formFields
|
||||
**
|
||||
|
@ -124,7 +124,23 @@ public class QFunctionInputMetaData
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for fieldList
|
||||
** Fluently ADD a list of fields to this object's existing list
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QFunctionInputMetaData withFields(List<QFieldMetaData> fieldList)
|
||||
{
|
||||
if(this.fieldList == null)
|
||||
{
|
||||
this.fieldList = new ArrayList<>();
|
||||
}
|
||||
this.fieldList.addAll(fieldList);
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent Setter for fieldList - e.g., will overwrite any previously set fields!!
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QFunctionInputMetaData withFieldList(List<QFieldMetaData> fieldList)
|
||||
@ -136,10 +152,10 @@ public class QFunctionInputMetaData
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for fieldList
|
||||
** Fluently add a field to the list
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QFunctionInputMetaData addField(QFieldMetaData field)
|
||||
public QFunctionInputMetaData withField(QFieldMetaData field)
|
||||
{
|
||||
if(this.fieldList == null)
|
||||
{
|
||||
@ -149,4 +165,17 @@ public class QFunctionInputMetaData
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Use withField instead, please.
|
||||
**
|
||||
** @deprecated
|
||||
*******************************************************************************/
|
||||
@Deprecated
|
||||
public QFunctionInputMetaData addField(QFieldMetaData field)
|
||||
{
|
||||
return (withField(field));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
*******************************************************************************/
|
||||
public class QRecordListMetaData
|
||||
{
|
||||
private String tableName;
|
||||
private String tableName;
|
||||
private Map<String, QFieldMetaData> fields;
|
||||
|
||||
|
||||
@ -116,7 +116,7 @@ public class QRecordListMetaData
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QRecordListMetaData addField(QFieldMetaData field)
|
||||
public QRecordListMetaData withField(QFieldMetaData field)
|
||||
{
|
||||
if(this.fields == null)
|
||||
{
|
||||
@ -126,4 +126,15 @@ public class QRecordListMetaData
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Deprecated
|
||||
public QRecordListMetaData addField(QFieldMetaData field)
|
||||
{
|
||||
return (withField(field));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ import com.kingsrook.qqq.backend.core.actions.interfaces.DeleteInterface;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -45,11 +44,7 @@ public class MockDeleteAction implements DeleteInterface
|
||||
{
|
||||
DeleteOutput rs = new DeleteOutput();
|
||||
|
||||
rs.setRecords(deleteInput.getPrimaryKeys().stream().map(primaryKey ->
|
||||
new QRecord()
|
||||
.withTableName(deleteInput.getTableName())
|
||||
.withValue("id", primaryKey))
|
||||
.toList());
|
||||
rs.setDeletedRecordCount(deleteInput.getPrimaryKeys().size());
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import com.kingsrook.qqq.backend.core.actions.interfaces.InsertInterface;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
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.data.QRecord;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -46,6 +47,16 @@ public class MockInsertAction implements InsertInterface
|
||||
|
||||
rs.setRecords(insertInput.getRecords());
|
||||
|
||||
String primaryKeyField = insertInput.getTable().getPrimaryKeyField();
|
||||
int i = 1;
|
||||
for(QRecord record : rs.getRecords())
|
||||
{
|
||||
if(record.getValue(primaryKeyField) == null)
|
||||
{
|
||||
record.setValue(primaryKeyField, i++);
|
||||
}
|
||||
}
|
||||
|
||||
return rs;
|
||||
}
|
||||
catch(Exception e)
|
||||
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.processes.implementations.bulk.delete;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Backend step to do a bulk delete.
|
||||
*******************************************************************************/
|
||||
public class BulkDeleteStoreStep implements BackendStep
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||
{
|
||||
runBackendStepInput.getAsyncJobCallback().updateStatus("Deleting records in database...");
|
||||
runBackendStepInput.getAsyncJobCallback().clearCurrentAndTotal();
|
||||
|
||||
DeleteInput deleteInput = new DeleteInput(runBackendStepInput.getInstance());
|
||||
deleteInput.setSession(runBackendStepInput.getSession());
|
||||
deleteInput.setAsyncJobCallback(runBackendStepInput.getAsyncJobCallback());
|
||||
deleteInput.setTableName(runBackendStepInput.getTableName());
|
||||
|
||||
String queryFilterJSON = runBackendStepInput.getValueString("queryFilterJSON");
|
||||
if(StringUtils.hasContent(queryFilterJSON))
|
||||
{
|
||||
try
|
||||
{
|
||||
deleteInput.setQueryFilter(JsonUtils.toObject(queryFilterJSON, QQueryFilter.class));
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw (new QException("Error loading record query filter from process", e));
|
||||
}
|
||||
}
|
||||
else if(CollectionUtils.nullSafeHasContents(runBackendStepInput.getRecords()))
|
||||
{
|
||||
String primaryKeyField = runBackendStepInput.getTable().getPrimaryKeyField();
|
||||
List<Serializable> primaryKeyList = runBackendStepInput.getRecords().stream()
|
||||
.map(r -> r.getValue(primaryKeyField))
|
||||
.toList();
|
||||
deleteInput.setPrimaryKeys(primaryKeyList);
|
||||
}
|
||||
|
||||
DeleteAction deleteAction = new DeleteAction();
|
||||
DeleteOutput deleteOutput = deleteAction.execute(deleteInput);
|
||||
|
||||
// todo - something with the output!!
|
||||
deleteOutput.getRecordsWithErrors();
|
||||
|
||||
runBackendStepOutput.setRecords(runBackendStepInput.getRecords());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.processes.implementations.bulk.edit;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Backend step to receive values for a bulk edit.
|
||||
*******************************************************************************/
|
||||
public class BulkEditReceiveValuesStep implements BackendStep
|
||||
{
|
||||
public static final String FIELD_ENABLED_FIELDS = "bulkEditEnabledFields";
|
||||
public static final String FIELD_VALUES_BEING_UPDATED = "valuesBeingUpdated";
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||
{
|
||||
String enabledFieldsString = runBackendStepInput.getValueString(FIELD_ENABLED_FIELDS);
|
||||
String[] enabledFields = enabledFieldsString.split(",");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// put the value in all the records (note, this is just for display on the review screen, //
|
||||
// and/or if we wanted to do some validation - this is NOT what will be store, as the //
|
||||
// Update action only wants fields that are being changed. //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
for(QRecord record : runBackendStepInput.getRecords())
|
||||
{
|
||||
for(String fieldName : enabledFields)
|
||||
{
|
||||
Serializable value = runBackendStepInput.getValue(fieldName);
|
||||
record.setValue(fieldName, value);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// build the string to show the user what fields are being changed //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
List<String> valuesBeingUpdated = new ArrayList<>();
|
||||
QTableMetaData table = runBackendStepInput.getTable();
|
||||
for(String fieldName : enabledFields)
|
||||
{
|
||||
String label = table.getField(fieldName).getLabel();
|
||||
Serializable value = runBackendStepInput.getValue(fieldName);
|
||||
|
||||
if(StringUtils.hasContent(ValueUtils.getValueAsString(value)))
|
||||
{
|
||||
valuesBeingUpdated.add(label + " will be set to: " + value);
|
||||
}
|
||||
else
|
||||
{
|
||||
valuesBeingUpdated.add(label + " will be cleared out.");
|
||||
}
|
||||
}
|
||||
runBackendStepOutput.addValue(FIELD_VALUES_BEING_UPDATED, String.join("\n", valuesBeingUpdated));
|
||||
|
||||
runBackendStepOutput.setRecords(runBackendStepInput.getRecords());
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.processes.implementations.bulk.edit;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Backend step to store the records from a bulk insert file
|
||||
*******************************************************************************/
|
||||
public class BulkEditStoreRecordsStep implements BackendStep
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||
{
|
||||
String enabledFieldsString = runBackendStepInput.getValueString(BulkEditReceiveValuesStep.FIELD_ENABLED_FIELDS);
|
||||
String[] enabledFields = enabledFieldsString.split(",");
|
||||
QTableMetaData table = runBackendStepInput.getTable();
|
||||
List<QRecord> recordsToUpdate = new ArrayList<>();
|
||||
|
||||
runBackendStepInput.getAsyncJobCallback().updateStatus("Updating values in records...");
|
||||
int i = 1;
|
||||
for(QRecord record : runBackendStepInput.getRecords())
|
||||
{
|
||||
runBackendStepInput.getAsyncJobCallback().updateStatus(i++, runBackendStepInput.getRecords().size());
|
||||
QRecord recordToUpdate = new QRecord();
|
||||
recordsToUpdate.add(recordToUpdate);
|
||||
|
||||
recordToUpdate.setValue(table.getPrimaryKeyField(), record.getValue(table.getPrimaryKeyField()));
|
||||
for(String fieldName : enabledFields)
|
||||
{
|
||||
Serializable value = runBackendStepInput.getValue(fieldName);
|
||||
recordToUpdate.setValue(fieldName, value);
|
||||
}
|
||||
}
|
||||
|
||||
runBackendStepInput.getAsyncJobCallback().updateStatus("Updating database...");
|
||||
runBackendStepInput.getAsyncJobCallback().clearCurrentAndTotal();
|
||||
|
||||
UpdateInput updateInput = new UpdateInput(runBackendStepInput.getInstance());
|
||||
updateInput.setSession(runBackendStepInput.getSession());
|
||||
updateInput.setAsyncJobCallback(runBackendStepInput.getAsyncJobCallback());
|
||||
updateInput.setAreAllValuesBeingUpdatedTheSame(true);
|
||||
updateInput.setTableName(runBackendStepInput.getTableName());
|
||||
updateInput.setRecords(recordsToUpdate);
|
||||
|
||||
UpdateAction updateAction = new UpdateAction();
|
||||
UpdateOutput updateOutput = updateAction.execute(updateInput);
|
||||
|
||||
runBackendStepOutput.setRecords(updateOutput.getRecords());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.processes.implementations.bulk.insert;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Backend step to receive a bulk-insert upload file
|
||||
*******************************************************************************/
|
||||
public class BulkInsertReceiveFileStep implements BackendStep
|
||||
{
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||
{
|
||||
List<QRecord> qRecords = BulkInsertUtils.getQRecordsFromFile(runBackendStepInput);
|
||||
|
||||
runBackendStepOutput.addValue("noOfFileRows", qRecords.size());
|
||||
runBackendStepOutput.setRecords(qRecords);
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.processes.implementations.bulk.insert;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
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.data.QRecord;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Backend step to store the records from a bulk insert file
|
||||
*******************************************************************************/
|
||||
public class BulkInsertStoreRecordsStep implements BackendStep
|
||||
{
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||
{
|
||||
List<QRecord> qRecords = BulkInsertUtils.getQRecordsFromFile(runBackendStepInput);
|
||||
|
||||
InsertInput insertInput = new InsertInput(runBackendStepInput.getInstance());
|
||||
insertInput.setSession(runBackendStepInput.getSession());
|
||||
insertInput.setTableName(runBackendStepInput.getTableName());
|
||||
insertInput.setRecords(qRecords);
|
||||
|
||||
InsertAction insertAction = new InsertAction();
|
||||
InsertOutput insertOutput = insertAction.execute(insertInput);
|
||||
|
||||
runBackendStepOutput.setRecords(insertOutput.getRecords());
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.processes.implementations.bulk.insert;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import com.kingsrook.qqq.backend.core.adapters.CsvToQRecordAdapter;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.QUploadedFile;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.QKeyBasedFieldMapping;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.state.AbstractStateKey;
|
||||
import com.kingsrook.qqq.backend.core.state.TempFileStateProvider;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Utility methods used by bulk insert steps
|
||||
*******************************************************************************/
|
||||
public class BulkInsertUtils
|
||||
{
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
static List<QRecord> getQRecordsFromFile(RunBackendStepInput runBackendStepInput) throws QException
|
||||
{
|
||||
AbstractStateKey stateKey = (AbstractStateKey) runBackendStepInput.getValue("uploadedFileKey");
|
||||
Optional<QUploadedFile> optionalUploadedFile = TempFileStateProvider.getInstance().get(QUploadedFile.class, stateKey);
|
||||
if(optionalUploadedFile.isEmpty())
|
||||
{
|
||||
throw (new QException("Could not find uploaded file"));
|
||||
}
|
||||
|
||||
byte[] bytes = optionalUploadedFile.get().getBytes();
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// let the user specify field labels instead names //
|
||||
/////////////////////////////////////////////////////
|
||||
QTableMetaData table = runBackendStepInput.getTable();
|
||||
QKeyBasedFieldMapping mapping = new QKeyBasedFieldMapping();
|
||||
for(Map.Entry<String, QFieldMetaData> entry : table.getFields().entrySet())
|
||||
{
|
||||
mapping.addMapping(entry.getKey(), entry.getValue().getLabel());
|
||||
}
|
||||
|
||||
// todo - sniff out file type...
|
||||
String tableName = runBackendStepInput.getTableName();
|
||||
List<QRecord> qRecords = new CsvToQRecordAdapter().buildRecordsFromCsv(new String(bytes), runBackendStepInput.getInstance().getTable(tableName), mapping);
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// remove values from any non-editable fields //
|
||||
////////////////////////////////////////////////
|
||||
List<QFieldMetaData> nonEditableFields = table.getFields().values().stream()
|
||||
.filter(f -> !f.getIsEditable())
|
||||
.toList();
|
||||
if(!nonEditableFields.isEmpty())
|
||||
{
|
||||
for(QRecord qRecord : qRecords)
|
||||
{
|
||||
for(QFieldMetaData nonEditableField : nonEditableFields)
|
||||
{
|
||||
qRecord.setValue(nonEditableField.getName(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (qRecords);
|
||||
}
|
||||
}
|
@ -26,12 +26,14 @@ import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
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.code.QCodeUsage;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QRecordListMetaData;
|
||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -49,8 +51,12 @@ public class LoadInitialRecordsStep implements BackendStep
|
||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// actually, this is a no-op... we Just need a backendStep to be the first step in the process //
|
||||
// basically this is a no-op... we Just need a backendStep to be the first step in the process //
|
||||
// but, while we're here, go ahead and put the query filter in the payload as a value, in case //
|
||||
// someone else wants it (see BulkDelete) //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
QQueryFilter queryFilter = runBackendStepInput.getCallback().getQueryFilter();
|
||||
runBackendStepOutput.addValue("queryFilterJSON", JsonUtils.toJson(queryFilter));
|
||||
}
|
||||
|
||||
|
||||
|
@ -49,20 +49,22 @@ public class MockBackendStep implements BackendStep
|
||||
@Override
|
||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||
{
|
||||
runBackendStepOutput.getRecords().forEach(r ->
|
||||
{
|
||||
r.setValue(FIELD_MOCK_VALUE, "Ha ha!");
|
||||
LOG.info("We are mocking {}: {}", r.getValueString("firstName"), r.getValue(FIELD_MOCK_VALUE));
|
||||
});
|
||||
|
||||
runBackendStepOutput.setValues(runBackendStepInput.getValues());
|
||||
runBackendStepOutput.addValue(FIELD_MOCK_VALUE, MOCK_VALUE);
|
||||
|
||||
/////////////////////////////////
|
||||
// mock the "greet" process... //
|
||||
/////////////////////////////////
|
||||
runBackendStepOutput.addValue("outputMessage", runBackendStepInput.getValueString(FIELD_GREETING_PREFIX) + " X " + runBackendStepInput.getValueString(FIELD_GREETING_SUFFIX));
|
||||
|
||||
runBackendStepInput.getRecords().forEach(r ->
|
||||
{
|
||||
LOG.info("We are mocking {}: {}", r.getValueString("firstName"), r.getValue(FIELD_MOCK_VALUE));
|
||||
r.setValue(FIELD_MOCK_VALUE, "Ha ha!");
|
||||
r.setValue("greetingMessage", runBackendStepInput.getValueString(FIELD_GREETING_PREFIX) + " " + r.getValueString("firstName") + " " + runBackendStepInput.getValueString(FIELD_GREETING_SUFFIX));
|
||||
});
|
||||
|
||||
runBackendStepOutput.setValues(runBackendStepInput.getValues());
|
||||
runBackendStepOutput.addValue(FIELD_MOCK_VALUE, MOCK_VALUE);
|
||||
runBackendStepOutput.addValue("noOfPeopleGreeted", runBackendStepInput.getRecords().size());
|
||||
|
||||
if("there".equalsIgnoreCase(runBackendStepInput.getValueString(FIELD_GREETING_SUFFIX)))
|
||||
{
|
||||
throw (new QException("You said Hello There, didn't you..."));
|
||||
|
@ -22,10 +22,13 @@
|
||||
package com.kingsrook.qqq.backend.core.state;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public abstract class AbstractStateKey
|
||||
public abstract class AbstractStateKey implements Serializable
|
||||
{
|
||||
/*******************************************************************************
|
||||
** Make the key give a unique string to identify itself.
|
||||
|
@ -31,5 +31,7 @@ package com.kingsrook.qqq.backend.core.state;
|
||||
public enum StateType
|
||||
{
|
||||
PROCESS_STATUS,
|
||||
ASYNC_JOB_STATUS
|
||||
ASYNC_JOB_STATUS,
|
||||
ASYNC_JOB_RESULT,
|
||||
UPLOADED_FILE
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
package com.kingsrook.qqq.backend.core.state;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -29,7 +30,7 @@ import java.util.UUID;
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class UUIDAndTypeStateKey extends AbstractStateKey
|
||||
public class UUIDAndTypeStateKey extends AbstractStateKey implements Serializable
|
||||
{
|
||||
private final UUID uuid;
|
||||
private final StateType stateType;
|
||||
|
@ -109,6 +109,7 @@ public class RunBackendStepActionTest
|
||||
XYZ""";
|
||||
case HTML -> "<b>Oh my</b>";
|
||||
case PASSWORD -> "myPa**word";
|
||||
case BLOB -> new byte[] { 1, 2, 3, 4 };
|
||||
});
|
||||
}
|
||||
return (rs);
|
||||
|
@ -26,10 +26,14 @@ import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -53,8 +57,28 @@ class DeleteActionTest
|
||||
request.setPrimaryKeys(List.of(1, 2));
|
||||
DeleteOutput result = new DeleteAction().execute(request);
|
||||
assertNotNull(result);
|
||||
assertEquals(2, result.getRecords().size());
|
||||
// todo - add errors to QRecord? assertTrue(result.getRecords().stream().allMatch(r -> r.getErrors() == null));
|
||||
assertEquals(2, result.getDeletedRecordCount());
|
||||
assertTrue(CollectionUtils.nullSafeIsEmpty(result.getRecordsWithErrors()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testErrorIfBothPrimaryKeysAndFilter()
|
||||
{
|
||||
DeleteInput request = new DeleteInput(TestUtils.defineInstance());
|
||||
request.setSession(TestUtils.getMockSession());
|
||||
request.setTableName("person");
|
||||
request.setPrimaryKeys(List.of(1, 2));
|
||||
request.setQueryFilter(new QQueryFilter());
|
||||
|
||||
assertThrows(QException.class, () ->
|
||||
{
|
||||
new DeleteAction().execute(request);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.processes.implementations.bulk.delete;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for BulkDeleteStoreStep
|
||||
*******************************************************************************/
|
||||
class BulkDeleteStoreStepTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testWithoutFilter() throws QException
|
||||
{
|
||||
RunBackendStepInput stepInput = new RunBackendStepInput(TestUtils.defineInstance());
|
||||
stepInput.setSession(TestUtils.getMockSession());
|
||||
stepInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
stepInput.setRecords(TestUtils.queryTable(TestUtils.defineTablePerson().getName()));
|
||||
|
||||
RunBackendStepOutput stepOutput = new RunBackendStepOutput();
|
||||
new BulkDeleteStoreStep().run(stepInput, stepOutput);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testWithFilter() throws QException
|
||||
{
|
||||
RunBackendStepInput stepInput = new RunBackendStepInput(TestUtils.defineInstance());
|
||||
stepInput.setSession(TestUtils.getMockSession());
|
||||
stepInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
stepInput.addValue("queryFilterJSON", JsonUtils.toJson(new QQueryFilter()));
|
||||
|
||||
RunBackendStepOutput stepOutput = new RunBackendStepOutput();
|
||||
new BulkDeleteStoreStep().run(stepInput, stepOutput);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.processes.implementations.bulk.edit;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for BulkEditReceiveValuesStep
|
||||
*******************************************************************************/
|
||||
class BulkEditReceiveValuesStepTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
RunBackendStepInput stepInput = new RunBackendStepInput(TestUtils.defineInstance());
|
||||
stepInput.setSession(TestUtils.getMockSession());
|
||||
stepInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
stepInput.addValue(BulkEditReceiveValuesStep.FIELD_ENABLED_FIELDS, "firstName,email,birthDate");
|
||||
stepInput.addValue("firstName", "Johnny");
|
||||
stepInput.addValue("email", null);
|
||||
stepInput.addValue("birthDate", "1909-01-09");
|
||||
List<QRecord> records = TestUtils.queryTable(TestUtils.defineTablePerson().getName());
|
||||
stepInput.setRecords(records);
|
||||
|
||||
RunBackendStepOutput stepOutput = new RunBackendStepOutput();
|
||||
new BulkEditReceiveValuesStep().run(stepInput, stepOutput);
|
||||
|
||||
String valuesBeingUpdated = stepOutput.getValueString(BulkEditReceiveValuesStep.FIELD_VALUES_BEING_UPDATED);
|
||||
assertThat(valuesBeingUpdated).matches("(?s).*First Name.*Johnny.*");
|
||||
assertThat(valuesBeingUpdated).matches("(?s).*Email will be cleared.*");
|
||||
assertThat(valuesBeingUpdated).matches("(?s).*Birth Date.*1909-01-09.*");
|
||||
|
||||
int count = 0;
|
||||
for(QRecord record : stepOutput.getRecords())
|
||||
{
|
||||
assertEquals("Johnny", record.getValueString("firstName"));
|
||||
assertNull(record.getValue("email"));
|
||||
// todo value utils needed in getValueDate... assertEquals(LocalDate.of(1909, 1, 9), record.getValueDate("birthDate"));
|
||||
count++;
|
||||
}
|
||||
assertEquals(records.size(), count);
|
||||
}
|
||||
|
||||
}
|
@ -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.processes.implementations.bulk.edit;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
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.assertNull;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for BulkEditStoreRecordsStep
|
||||
*******************************************************************************/
|
||||
class BulkEditStoreRecordsStepTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
RunBackendStepInput stepInput = new RunBackendStepInput(TestUtils.defineInstance());
|
||||
stepInput.setSession(TestUtils.getMockSession());
|
||||
stepInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
stepInput.addValue(BulkEditReceiveValuesStep.FIELD_ENABLED_FIELDS, "firstName,email,birthDate");
|
||||
stepInput.addValue("firstName", "Johnny");
|
||||
stepInput.addValue("email", null);
|
||||
stepInput.addValue("birthDate", "1909-01-09");
|
||||
List<QRecord> records = TestUtils.queryTable(TestUtils.defineTablePerson().getName());
|
||||
stepInput.setRecords(records);
|
||||
|
||||
RunBackendStepOutput stepOutput = new RunBackendStepOutput();
|
||||
new BulkEditStoreRecordsStep().run(stepInput, stepOutput);
|
||||
|
||||
assertRecordValues(stepOutput.getRecords());
|
||||
|
||||
// re-fetch the records, make sure they are updated.
|
||||
// but since Mock backend doesn't actually update them, we can't do this..
|
||||
// todo - implement an in-memory backend, that would do this.
|
||||
// List<QRecord> updatedRecords = TestUtils.queryTable(TestUtils.defineTablePerson().getName());
|
||||
// assertRecordValues(updatedRecords);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void assertRecordValues(List<QRecord> records)
|
||||
{
|
||||
for(QRecord record : records)
|
||||
{
|
||||
assertEquals("Johnny", record.getValueString("firstName"));
|
||||
assertNull(record.getValue("email"));
|
||||
// todo value utils needed in getValueDate... assertEquals(LocalDate.of(1909, 1, 9), record.getValueDate("birthDate"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.processes.implementations.bulk.insert;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.QUploadedFile;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.state.StateType;
|
||||
import com.kingsrook.qqq.backend.core.state.TempFileStateProvider;
|
||||
import com.kingsrook.qqq.backend.core.state.UUIDAndTypeStateKey;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for BulkInsertReceiveFileStep
|
||||
*******************************************************************************/
|
||||
class BulkInsertReceiveFileStepTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////
|
||||
// create an uploaded file, similar to how an http server may //
|
||||
////////////////////////////////////////////////////////////////
|
||||
QUploadedFile qUploadedFile = new QUploadedFile();
|
||||
qUploadedFile.setBytes((TestUtils.getPersonCsvHeaderUsingLabels() + TestUtils.getPersonCsvRow1() + TestUtils.getPersonCsvRow2()).getBytes());
|
||||
qUploadedFile.setFilename("test.csv");
|
||||
UUIDAndTypeStateKey key = new UUIDAndTypeStateKey(StateType.UPLOADED_FILE);
|
||||
TempFileStateProvider.getInstance().put(key, qUploadedFile);
|
||||
|
||||
////////////////////////////
|
||||
// setup and run the step //
|
||||
////////////////////////////
|
||||
RunBackendStepInput stepInput = new RunBackendStepInput(TestUtils.defineInstance());
|
||||
stepInput.setSession(TestUtils.getMockSession());
|
||||
stepInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
stepInput.addValue("uploadedFileKey", key);
|
||||
|
||||
RunBackendStepOutput stepOutput = new RunBackendStepOutput();
|
||||
new BulkInsertReceiveFileStep().run(stepInput, stepOutput);
|
||||
|
||||
List<QRecord> records = stepOutput.getRecords();
|
||||
assertEquals(2, records.size());
|
||||
assertEquals("John", records.get(0).getValueString("firstName"));
|
||||
assertEquals("Jane", records.get(1).getValueString("firstName"));
|
||||
assertNull(records.get(0).getValue("id"));
|
||||
assertNull(records.get(1).getValue("id"));
|
||||
|
||||
assertEquals(2, stepOutput.getValueInteger("noOfFileRows"));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.processes.implementations.bulk.insert;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.QUploadedFile;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.state.StateType;
|
||||
import com.kingsrook.qqq.backend.core.state.TempFileStateProvider;
|
||||
import com.kingsrook.qqq.backend.core.state.UUIDAndTypeStateKey;
|
||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for BulkInsertStoreRecordsStep
|
||||
*******************************************************************************/
|
||||
class BulkInsertStoreRecordsStepTest
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test() throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////
|
||||
// create an uploaded file, similar to how an http server may //
|
||||
////////////////////////////////////////////////////////////////
|
||||
QUploadedFile qUploadedFile = new QUploadedFile();
|
||||
qUploadedFile.setBytes((TestUtils.getPersonCsvHeaderUsingLabels() + TestUtils.getPersonCsvRow1() + TestUtils.getPersonCsvRow2()).getBytes());
|
||||
qUploadedFile.setFilename("test.csv");
|
||||
UUIDAndTypeStateKey key = new UUIDAndTypeStateKey(StateType.UPLOADED_FILE);
|
||||
TempFileStateProvider.getInstance().put(key, qUploadedFile);
|
||||
|
||||
////////////////////////////
|
||||
// setup and run the step //
|
||||
////////////////////////////
|
||||
RunBackendStepInput stepInput = new RunBackendStepInput(TestUtils.defineInstance());
|
||||
stepInput.setSession(TestUtils.getMockSession());
|
||||
stepInput.setTableName(TestUtils.defineTablePerson().getName());
|
||||
stepInput.addValue("uploadedFileKey", key);
|
||||
|
||||
RunBackendStepOutput stepOutput = new RunBackendStepOutput();
|
||||
new BulkInsertStoreRecordsStep().run(stepInput, stepOutput);
|
||||
|
||||
List<QRecord> records = stepOutput.getRecords();
|
||||
assertEquals(2, records.size());
|
||||
assertEquals("John", records.get(0).getValueString("firstName"));
|
||||
assertEquals("Jane", records.get(1).getValueString("firstName"));
|
||||
assertNotNull(records.get(0).getValue("id"));
|
||||
assertNotNull(records.get(1).getValue("id"));
|
||||
}
|
||||
|
||||
}
|
@ -25,7 +25,12 @@ package com.kingsrook.qqq.backend.core.utils;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.person.addtopeoplesage.AddAge;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.person.addtopeoplesage.GetAgeStatistics;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.adapters.QInstanceAdapter;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
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.processes.implementations.mock.MockBackendStep;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
||||
@ -56,8 +61,8 @@ import com.kingsrook.qqq.backend.core.processes.implementations.etl.basic.BasicE
|
||||
*******************************************************************************/
|
||||
public class TestUtils
|
||||
{
|
||||
public static String DEFAULT_BACKEND_NAME = "default";
|
||||
public static String PROCESS_NAME_GREET_PEOPLE = "greet";
|
||||
public static String DEFAULT_BACKEND_NAME = "default";
|
||||
public static String PROCESS_NAME_GREET_PEOPLE = "greet";
|
||||
public static String PROCESS_NAME_GREET_PEOPLE_INTERACTIVE = "greetInteractive";
|
||||
|
||||
|
||||
@ -136,9 +141,9 @@ public class TestUtils
|
||||
.withLabel("Person")
|
||||
.withBackendName(DEFAULT_BACKEND_NAME)
|
||||
.withPrimaryKeyField("id")
|
||||
.withField(new QFieldMetaData("id", QFieldType.INTEGER))
|
||||
.withField(new QFieldMetaData("createDate", QFieldType.DATE_TIME))
|
||||
.withField(new QFieldMetaData("modifyDate", QFieldType.DATE_TIME))
|
||||
.withField(new QFieldMetaData("id", QFieldType.INTEGER).withIsEditable(false))
|
||||
.withField(new QFieldMetaData("createDate", QFieldType.DATE_TIME).withIsEditable(false))
|
||||
.withField(new QFieldMetaData("modifyDate", QFieldType.DATE_TIME).withIsEditable(false))
|
||||
.withField(new QFieldMetaData("firstName", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("lastName", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("birthDate", QFieldType.DATE))
|
||||
@ -306,4 +311,67 @@ public class TestUtils
|
||||
MockAuthenticationModule mockAuthenticationModule = new MockAuthenticationModule();
|
||||
return (mockAuthenticationModule.createSession(null));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static List<QRecord> queryTable(String tableName) throws QException
|
||||
{
|
||||
QueryInput queryInput = new QueryInput(TestUtils.defineInstance());
|
||||
queryInput.setSession(TestUtils.getMockSession());
|
||||
queryInput.setTableName(tableName);
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
return (queryOutput.getRecords());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static String getPersonCsvHeader()
|
||||
{
|
||||
return ("""
|
||||
"id","createDate","modifyDate","firstName","lastName","birthDate","email"\r
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static String getPersonCsvHeaderUsingLabels()
|
||||
{
|
||||
return ("""
|
||||
"Id","Create Date","Modify Date","First Name","Last Name","Birth Date","Email"\r
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static String getPersonCsvRow1()
|
||||
{
|
||||
return ("""
|
||||
"0","2021-10-26 14:39:37","2021-10-26 14:39:37","John","Doe","1980-01-01","john@doe.com"\r
|
||||
""");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static String getPersonCsvRow2()
|
||||
{
|
||||
return ("""
|
||||
"0","2021-10-26 14:39:37","2021-10-26 14:39:37","Jane","Doe","1981-01-01","john@doe.com"\r
|
||||
""");
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user