mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-20 22:18:43 +00:00
Compare commits
42 Commits
snapshot
...
version-0.
Author | SHA1 | Date | |
---|---|---|---|
6702c06ed0 | |||
9dfbd839c8 | |||
724d5779cc | |||
1fef376e65 | |||
d3417a0652 | |||
053d5f1058 | |||
47e27d5ffc | |||
59a70a4cb7 | |||
fea757c46d | |||
9a65ea81b2 | |||
494ec00b84 | |||
9b4b61af38 | |||
f237b5e82d | |||
207311eb0b | |||
ab5af234af | |||
9baa7c32bf | |||
3eae3a5758 | |||
a11d584c8a | |||
ba3cf53c30 | |||
d44790545d | |||
5aed59b9b1 | |||
3bcc0a17bc | |||
09c4d99612 | |||
26fc4fb4e0 | |||
d92be4e69b | |||
2de3306f95 | |||
58b0936c50 | |||
51eb7d89be | |||
0b5e97d596 | |||
2609bc801c | |||
583d702355 | |||
06a69279a8 | |||
9a2276edf2 | |||
36307dba24 | |||
fa2b1c0b8e | |||
840e1aada3 | |||
22d5bc547c | |||
b7cfea157d | |||
028751e23a | |||
be0e1f9c0b | |||
912e40fe0b | |||
f9af2ba983 |
@ -213,18 +213,6 @@
|
||||
<property name="tokens" value="VARIABLE_DEF"/>
|
||||
<property name="allowSamelineMultipleAnnotations" value="true"/>
|
||||
</module>
|
||||
<module name="NonEmptyAtclauseDescription"/>
|
||||
<!-- <module name="JavadocTagContinuationIndentation"/> -->
|
||||
<!--
|
||||
<module name="SummaryJavadoc">
|
||||
<property name="forbiddenSummaryFragments" value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
|
||||
</module>
|
||||
-->
|
||||
<!-- <module name="JavadocParagraph"/> -->
|
||||
<module name="AtclauseOrder">
|
||||
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
|
||||
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
|
||||
</module>
|
||||
<module name="JavadocMethod">
|
||||
<property name="allowMissingParamTags" value="true"/>
|
||||
<property name="allowMissingReturnTag" value="true"/>
|
||||
@ -233,23 +221,14 @@
|
||||
<module name="MissingJavadocMethod">
|
||||
<property name="scope" value="private"/>
|
||||
</module>
|
||||
<module name="MissingJavadocType">
|
||||
<property name="scope" value="private"/>
|
||||
</module>
|
||||
<module name="MethodName">
|
||||
<property name="format" value="^[a-z][a-zA-Z0-9_]*$"/>
|
||||
<message key="name.invalidPattern"
|
||||
value="Method name ''{0}'' must match pattern ''{1}''."/>
|
||||
</module>
|
||||
<module name="SingleLineJavadoc">
|
||||
<property name="ignoreInlineTags" value="false"/>
|
||||
</module>
|
||||
|
||||
<module name="MagicNumber">
|
||||
<property name="severity" value="info"/>
|
||||
<property name="tokens" value="NUM_DOUBLE, NUM_FLOAT, NUM_INT"/>
|
||||
<property name="ignoreNumbers" value="0, 1, 2, 3, 4, 5, 6, 7, 8"/>
|
||||
<property name="ignoreFieldDeclaration" value="true"/>
|
||||
<property name="ignoreAnnotation" value="true"/>
|
||||
</module>
|
||||
|
||||
<module name="EmptyCatchBlock">
|
||||
<property name="exceptionVariableName" value="expected"/>
|
||||
</module>
|
||||
|
@ -33,9 +33,6 @@ If the {link-table} has a `POST_QUERY_CUSTOMIZER` defined, then after records ar
|
||||
* `table` - *String, Required* - Name of the table being queried against.
|
||||
* `filter` - *<<QQueryFilter>> object* - Specification for what records should be returned, based on *<<QFilterCriteria>>* objects, and how they should be sorted, based on *<<QFilterOrderBy>>* objects.
|
||||
If a `filter` is not given, then all rows in the table will be returned by the query.
|
||||
* `skip` - *Integer* - Optional number of records to be skipped at the beginning of the result set.
|
||||
e.g., for implementing pagination.
|
||||
* `limit` - *Integer* - Optional maximum number of records to be returned by the query.
|
||||
* `transaction` - *QBackendTransaction object* - Optional transaction object.
|
||||
** Behavior for this object is backend-dependant.
|
||||
In an RDBMS backend, this object is generally needed if you want your query to see data that may have been modified within the same transaction.
|
||||
@ -55,6 +52,14 @@ But if running a query to provide data as part of a process, then this can gener
|
||||
* `shouldMaskPassword` - *boolean, default: true* - Controls whether or not fields with `type` = `PASSWORD` should be masked, or if their actual values should be returned.
|
||||
* `queryJoins` - *List of <<QueryJoin>> objects* - Optional list of tables to be joined with the main table being queried.
|
||||
See QueryJoin below for further details.
|
||||
* `fieldNamesToInclude` - *Set of String* - Optional set of field names to be included in the records.
|
||||
** Fields from a queryJoin must be prefixed by the join table's name or alias, and a period.
|
||||
Field names from the table being queried should not have any sort of prefix.
|
||||
** A `null` set here (default) means to include all fields from the table and any queryJoins set as select=true.
|
||||
** An empty set will cause an error, as well any unrecognized field names.
|
||||
** `QueryAction` will validate the set of field names, and throw an exception if any unrecognized names are given.
|
||||
** _Note that this is an optional feature, which some backend modules may not implement.
|
||||
Meaning, they would always return all fields._
|
||||
|
||||
==== QQueryFilter
|
||||
A key component of *<<QueryInput>>*, a *QQueryFilter* defines both what records should be included in a query's results (e.g., an SQL `WHERE`), as well as how those results should be sorted (SQL `ORDER BY`).
|
||||
@ -68,6 +73,9 @@ In general, multiple *orderBys* can be given (depending on backend implementatio
|
||||
** Each *subFilter* can include its own additional *subFilters*.
|
||||
** Each *subFilter* can specify a different *booleanOperator*.
|
||||
** For example, consider the following *QQueryFilter*, that uses two *subFilters*, and a mix of *booleanOperators*
|
||||
* `skip` - *Integer* - Optional number of records to be skipped at the beginning of the result set.
|
||||
e.g., for implementing pagination.
|
||||
* `limit` - *Integer* - Optional maximum number of records to be returned by the query.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
|
6
pom.xml
6
pom.xml
@ -46,12 +46,11 @@
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<revision>0.21.0-SNAPSHOT</revision>
|
||||
<revision>0.21.0</revision>
|
||||
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<maven.compiler.release>17</maven.compiler.release>
|
||||
<maven.compiler.showDeprecation>true</maven.compiler.showDeprecation>
|
||||
<maven.compiler.showWarnings>true</maven.compiler.showWarnings>
|
||||
<coverage.haltOnFailure>true</coverage.haltOnFailure>
|
||||
@ -168,6 +167,7 @@
|
||||
<violationSeverity>warning</violationSeverity>
|
||||
<excludes>**/target/generated-sources/*.*</excludes>
|
||||
<!-- <linkXRef>false</linkXRef> -->
|
||||
<includeTestSourceDirectory>true</includeTestSourceDirectory>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
|
@ -37,7 +37,7 @@ import com.kingsrook.qqq.backend.core.modules.backend.QBackendModuleInterface;
|
||||
**
|
||||
** Note: One would imagine that this class shouldn't ever implement Serializable...
|
||||
*******************************************************************************/
|
||||
public class QBackendTransaction
|
||||
public class QBackendTransaction implements AutoCloseable
|
||||
{
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -344,6 +344,9 @@ public class RecordAutomationStatusUpdater
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
private record Key(QTableMetaData table, TriggerEvent triggerEvent) {}
|
||||
|
||||
}
|
||||
|
@ -55,10 +55,10 @@ public abstract class AbstractPreInsertCustomizer implements TableCustomizerInte
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// allow the customizer to specify when it should be executed as part of the //
|
||||
// insert action. default (per method in this class) is AFTER_ALL_VALIDATIONS //
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/***************************************************************************
|
||||
** allow the customizer to specify when it should be executed as part of the
|
||||
** insert action. default (per method in this class) is AFTER_ALL_VALIDATIONS
|
||||
***************************************************************************/
|
||||
public enum WhenToRun
|
||||
{
|
||||
BEFORE_ALL_VALIDATIONS,
|
||||
|
@ -28,6 +28,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QRuntimeException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||
@ -49,6 +50,9 @@ import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
*******************************************************************************/
|
||||
public abstract class ChildInserterPostInsertCustomizer extends AbstractPostInsertCustomizer
|
||||
{
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public enum RelationshipType
|
||||
{
|
||||
PARENT_POINTS_AT_CHILD,
|
||||
@ -97,7 +101,7 @@ public abstract class ChildInserterPostInsertCustomizer extends AbstractPostInse
|
||||
List<QRecord> rs = records;
|
||||
List<QRecord> childrenToInsert = new ArrayList<>();
|
||||
QTableMetaData table = getInsertInput().getTable();
|
||||
QTableMetaData childTable = getInsertInput().getInstance().getTable(getChildTableName());
|
||||
QTableMetaData childTable = QContext.getQInstance().getTable(getChildTableName());
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// iterate over the inserted records, building a list child records to insert //
|
||||
|
@ -24,10 +24,12 @@ package com.kingsrook.qqq.backend.core.actions.customizers;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
@ -143,4 +145,19 @@ public interface RecordCustomizerUtilityInterface
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
default Map<Serializable, QRecord> getOldRecordMap(List<QRecord> oldRecordList, UpdateInput updateInput)
|
||||
{
|
||||
Map<Serializable, QRecord> oldRecordMap = new HashMap<>();
|
||||
for(QRecord qRecord : oldRecordList)
|
||||
{
|
||||
oldRecordMap.put(qRecord.getValue(updateInput.getTable().getPrimaryKeyField()), qRecord);
|
||||
}
|
||||
|
||||
return (oldRecordMap);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter;
|
||||
import com.kingsrook.qqq.backend.core.actions.values.SearchPossibleValueSourceAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||
@ -102,7 +103,7 @@ public abstract class AbstractWidgetRenderer
|
||||
String possibleValueSourceName = dropdownData.getPossibleValueSourceName();
|
||||
if(possibleValueSourceName != null)
|
||||
{
|
||||
QPossibleValueSource possibleValueSource = input.getInstance().getPossibleValueSource(possibleValueSourceName);
|
||||
QPossibleValueSource possibleValueSource = QContext.getQInstance().getPossibleValueSource(possibleValueSourceName);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// this looks complicated, but is just look for a label in the dropdown data and if found use it, //
|
||||
|
@ -34,6 +34,7 @@ import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
@ -181,10 +182,10 @@ public class ChildRecordListRenderer extends AbstractWidgetRenderer
|
||||
{
|
||||
String widgetLabel = input.getQueryParams().get("widgetLabel");
|
||||
String joinName = input.getQueryParams().get("joinName");
|
||||
QJoinMetaData join = input.getInstance().getJoin(joinName);
|
||||
QJoinMetaData join = QContext.getQInstance().getJoin(joinName);
|
||||
String id = input.getQueryParams().get("id");
|
||||
QTableMetaData leftTable = input.getInstance().getTable(join.getLeftTable());
|
||||
QTableMetaData rightTable = input.getInstance().getTable(join.getRightTable());
|
||||
QTableMetaData leftTable = QContext.getQInstance().getTable(join.getLeftTable());
|
||||
QTableMetaData rightTable = QContext.getQInstance().getTable(join.getRightTable());
|
||||
|
||||
Integer maxRows = null;
|
||||
if(StringUtils.hasContent(input.getQueryParams().get("maxRows")))
|
||||
@ -252,7 +253,7 @@ public class ChildRecordListRenderer extends AbstractWidgetRenderer
|
||||
}
|
||||
}
|
||||
|
||||
String tablePath = input.getInstance().getTablePath(rightTable.getName());
|
||||
String tablePath = QContext.getQInstance().getTablePath(rightTable.getName());
|
||||
String viewAllLink = tablePath == null ? null : (tablePath + "?filter=" + URLEncoder.encode(JsonUtils.toJson(filter), Charset.defaultCharset()));
|
||||
|
||||
ChildRecordListData widgetData = new ChildRecordListData(widgetLabel, queryOutput, rightTable, tablePath, viewAllLink, totalRows);
|
||||
@ -278,7 +279,9 @@ public class ChildRecordListRenderer extends AbstractWidgetRenderer
|
||||
Map<String, Serializable> widgetValues = input.getWidgetMetaData().getDefaultValues();
|
||||
if(widgetValues.containsKey("disabledFieldsForNewChildRecords"))
|
||||
{
|
||||
widgetData.setDisabledFieldsForNewChildRecords((Set<String>) widgetValues.get("disabledFieldsForNewChildRecords"));
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<String> disabledFieldsForNewChildRecords = (Set<String>) widgetValues.get("disabledFieldsForNewChildRecords");
|
||||
widgetData.setDisabledFieldsForNewChildRecords(disabledFieldsForNewChildRecords);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.core.actions.dashboard.widgets;
|
||||
|
||||
import java.util.HashMap;
|
||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetOutput;
|
||||
@ -57,7 +58,7 @@ public class ProcessWidgetRenderer extends AbstractWidgetRenderer
|
||||
setupDropdowns(input, widgetMetaData, data);
|
||||
|
||||
String processName = (String) widgetMetaData.getDefaultValues().get(WIDGET_PROCESS_NAME);
|
||||
QProcessMetaData processMetaData = input.getInstance().getProcess(processName);
|
||||
QProcessMetaData processMetaData = QContext.getQInstance().getProcess(processName);
|
||||
data.setProcessMetaData(processMetaData);
|
||||
|
||||
data.setDefaultValues(new HashMap<>(input.getQueryParams()));
|
||||
|
@ -30,6 +30,7 @@ import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||
import com.kingsrook.qqq.backend.core.actions.permissions.PermissionCheckResult;
|
||||
import com.kingsrook.qqq.backend.core.actions.permissions.PermissionsHelper;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput;
|
||||
@ -72,7 +73,7 @@ public class MetaDataAction
|
||||
// map tables to frontend metadata //
|
||||
/////////////////////////////////////
|
||||
Map<String, QFrontendTableMetaData> tables = new LinkedHashMap<>();
|
||||
for(Map.Entry<String, QTableMetaData> entry : metaDataInput.getInstance().getTables().entrySet())
|
||||
for(Map.Entry<String, QTableMetaData> entry : QContext.getQInstance().getTables().entrySet())
|
||||
{
|
||||
String tableName = entry.getKey();
|
||||
QTableMetaData table = entry.getValue();
|
||||
@ -83,7 +84,7 @@ public class MetaDataAction
|
||||
continue;
|
||||
}
|
||||
|
||||
QBackendMetaData backendForTable = metaDataInput.getInstance().getBackendForTable(tableName);
|
||||
QBackendMetaData backendForTable = QContext.getQInstance().getBackendForTable(tableName);
|
||||
tables.put(tableName, new QFrontendTableMetaData(metaDataInput, backendForTable, table, false, false));
|
||||
treeNodes.put(tableName, new AppTreeNode(table));
|
||||
}
|
||||
@ -96,7 +97,7 @@ public class MetaDataAction
|
||||
// map processes to frontend metadata //
|
||||
////////////////////////////////////////
|
||||
Map<String, QFrontendProcessMetaData> processes = new LinkedHashMap<>();
|
||||
for(Map.Entry<String, QProcessMetaData> entry : metaDataInput.getInstance().getProcesses().entrySet())
|
||||
for(Map.Entry<String, QProcessMetaData> entry : QContext.getQInstance().getProcesses().entrySet())
|
||||
{
|
||||
String processName = entry.getKey();
|
||||
QProcessMetaData process = entry.getValue();
|
||||
@ -116,7 +117,7 @@ public class MetaDataAction
|
||||
// map reports to frontend metadata //
|
||||
//////////////////////////////////////
|
||||
Map<String, QFrontendReportMetaData> reports = new LinkedHashMap<>();
|
||||
for(Map.Entry<String, QReportMetaData> entry : metaDataInput.getInstance().getReports().entrySet())
|
||||
for(Map.Entry<String, QReportMetaData> entry : QContext.getQInstance().getReports().entrySet())
|
||||
{
|
||||
String reportName = entry.getKey();
|
||||
QReportMetaData report = entry.getValue();
|
||||
@ -136,7 +137,7 @@ public class MetaDataAction
|
||||
// map widgets to frontend metadata //
|
||||
//////////////////////////////////////
|
||||
Map<String, QFrontendWidgetMetaData> widgets = new LinkedHashMap<>();
|
||||
for(Map.Entry<String, QWidgetMetaDataInterface> entry : metaDataInput.getInstance().getWidgets().entrySet())
|
||||
for(Map.Entry<String, QWidgetMetaDataInterface> entry : QContext.getQInstance().getWidgets().entrySet())
|
||||
{
|
||||
String widgetName = entry.getKey();
|
||||
QWidgetMetaDataInterface widget = entry.getValue();
|
||||
@ -154,7 +155,7 @@ public class MetaDataAction
|
||||
///////////////////////////////////////////////////////
|
||||
// sort apps - by sortOrder (integer), then by label //
|
||||
///////////////////////////////////////////////////////
|
||||
List<QAppMetaData> sortedApps = metaDataInput.getInstance().getApps().values().stream()
|
||||
List<QAppMetaData> sortedApps = QContext.getQInstance().getApps().values().stream()
|
||||
.sorted(Comparator.comparing((QAppMetaData a) -> a.getSortOrder())
|
||||
.thenComparing((QAppMetaData a) -> a.getLabel()))
|
||||
.toList();
|
||||
@ -211,14 +212,14 @@ public class MetaDataAction
|
||||
////////////////////////////////////
|
||||
// add branding metadata if found //
|
||||
////////////////////////////////////
|
||||
if(metaDataInput.getInstance().getBranding() != null)
|
||||
if(QContext.getQInstance().getBranding() != null)
|
||||
{
|
||||
metaDataOutput.setBranding(metaDataInput.getInstance().getBranding());
|
||||
metaDataOutput.setBranding(QContext.getQInstance().getBranding());
|
||||
}
|
||||
|
||||
metaDataOutput.setEnvironmentValues(metaDataInput.getInstance().getEnvironmentValues());
|
||||
metaDataOutput.setEnvironmentValues(QContext.getQInstance().getEnvironmentValues());
|
||||
|
||||
metaDataOutput.setHelpContents(metaDataInput.getInstance().getHelpContent());
|
||||
metaDataOutput.setHelpContents(QContext.getQInstance().getHelpContent());
|
||||
|
||||
// todo post-customization - can do whatever w/ the result if you want?
|
||||
|
||||
|
@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.core.actions.metadata;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.ProcessMetaDataInput;
|
||||
@ -47,7 +48,7 @@ public class ProcessMetaDataAction
|
||||
// todo pre-customization - just get to modify the request?
|
||||
ProcessMetaDataOutput processMetaDataOutput = new ProcessMetaDataOutput();
|
||||
|
||||
QProcessMetaData process = processMetaDataInput.getInstance().getProcess(processMetaDataInput.getProcessName());
|
||||
QProcessMetaData process = QContext.getQInstance().getProcess(processMetaDataInput.getProcessName());
|
||||
if(process == null)
|
||||
{
|
||||
throw (new QNotFoundException("Process [" + processMetaDataInput.getProcessName() + "] was not found."));
|
||||
|
@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.core.actions.metadata;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.TableMetaDataInput;
|
||||
@ -48,12 +49,12 @@ public class TableMetaDataAction
|
||||
// todo pre-customization - just get to modify the request?
|
||||
TableMetaDataOutput tableMetaDataOutput = new TableMetaDataOutput();
|
||||
|
||||
QTableMetaData table = tableMetaDataInput.getInstance().getTable(tableMetaDataInput.getTableName());
|
||||
QTableMetaData table = QContext.getQInstance().getTable(tableMetaDataInput.getTableName());
|
||||
if(table == null)
|
||||
{
|
||||
throw (new QNotFoundException("Table [" + tableMetaDataInput.getTableName() + "] was not found."));
|
||||
}
|
||||
QBackendMetaData backendForTable = tableMetaDataInput.getInstance().getBackendForTable(table.getName());
|
||||
QBackendMetaData backendForTable = QContext.getQInstance().getBackendForTable(table.getName());
|
||||
tableMetaDataOutput.setTable(new QFrontendTableMetaData(tableMetaDataInput, backendForTable, table, true, true));
|
||||
|
||||
// todo post-customization - can do whatever w/ the result if you want
|
||||
|
@ -25,6 +25,7 @@ package com.kingsrook.qqq.backend.core.actions.processes;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QBadRequestException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
@ -54,7 +55,7 @@ public class CancelProcessAction extends RunProcessAction
|
||||
{
|
||||
ActionHelper.validateSession(runProcessInput);
|
||||
|
||||
QProcessMetaData process = runProcessInput.getInstance().getProcess(runProcessInput.getProcessName());
|
||||
QProcessMetaData process = QContext.getQInstance().getProcess(runProcessInput.getProcessName());
|
||||
if(process == null)
|
||||
{
|
||||
throw new QBadRequestException("Process [" + runProcessInput.getProcessName() + "] is not defined in this instance.");
|
||||
|
@ -30,6 +30,7 @@ import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
@ -64,7 +65,7 @@ public class RunBackendStepAction
|
||||
{
|
||||
ActionHelper.validateSession(runBackendStepInput);
|
||||
|
||||
QProcessMetaData process = runBackendStepInput.getInstance().getProcess(runBackendStepInput.getProcessName());
|
||||
QProcessMetaData process = QContext.getQInstance().getProcess(runBackendStepInput.getProcessName());
|
||||
if(process == null)
|
||||
{
|
||||
throw new QException("Process [" + runBackendStepInput.getProcessName() + "] is not defined in this instance.");
|
||||
|
@ -99,7 +99,7 @@ public class RunProcessAction
|
||||
{
|
||||
ActionHelper.validateSession(runProcessInput);
|
||||
|
||||
QProcessMetaData process = runProcessInput.getInstance().getProcess(runProcessInput.getProcessName());
|
||||
QProcessMetaData process = QContext.getQInstance().getProcess(runProcessInput.getProcessName());
|
||||
if(process == null)
|
||||
{
|
||||
throw new QException("Process [" + runProcessInput.getProcessName() + "] is not defined in this instance.");
|
||||
|
@ -42,6 +42,7 @@ import com.kingsrook.qqq.backend.core.actions.AbstractQActionFunction;
|
||||
import com.kingsrook.qqq.backend.core.actions.async.AsyncRecordPipeLoop;
|
||||
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
|
||||
import com.kingsrook.qqq.backend.core.actions.reporting.customizers.DataSourceQueryInputCustomizer;
|
||||
import com.kingsrook.qqq.backend.core.actions.reporting.customizers.ReportCustomRecordSourceInterface;
|
||||
import com.kingsrook.qqq.backend.core.actions.reporting.customizers.ReportViewCustomizer;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
@ -302,10 +303,19 @@ public class GenerateReportAction extends AbstractQActionFunction<ReportInput, R
|
||||
JoinsContext joinsContext = null;
|
||||
if(dataSource != null)
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// count records, if applicable, from the data source - for populating into the //
|
||||
// countByDataSource map, as well as for checking if too many rows (e.g., for excel) //
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
countDataSourceRecords(reportInput, dataSource, reportFormat);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if there's a source table, set up a joins context, to use below for looking up fields //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(StringUtils.hasContent(dataSource.getSourceTable()))
|
||||
{
|
||||
joinsContext = new JoinsContext(QContext.getQInstance(), dataSource.getSourceTable(), cloneDataSourceQueryJoins(dataSource), dataSource.getQueryFilter() == null ? null : dataSource.getQueryFilter().clone());
|
||||
countDataSourceRecords(reportInput, dataSource, reportFormat);
|
||||
QQueryFilter queryFilter = dataSource.getQueryFilter() == null ? new QQueryFilter() : dataSource.getQueryFilter().clone();
|
||||
joinsContext = new JoinsContext(QContext.getQInstance(), dataSource.getSourceTable(), dataSource.getQueryJoins(), queryFilter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,6 +339,7 @@ public class GenerateReportAction extends AbstractQActionFunction<ReportInput, R
|
||||
field.setName(column.getName());
|
||||
if(StringUtils.hasContent(column.getLabel()))
|
||||
{
|
||||
|
||||
field.setLabel(column.getLabel());
|
||||
}
|
||||
fields.add(field);
|
||||
@ -346,23 +357,33 @@ public class GenerateReportAction extends AbstractQActionFunction<ReportInput, R
|
||||
*******************************************************************************/
|
||||
private void countDataSourceRecords(ReportInput reportInput, QReportDataSource dataSource, ReportFormat reportFormat) throws QException
|
||||
{
|
||||
QQueryFilter queryFilter = dataSource.getQueryFilter() == null ? new QQueryFilter() : dataSource.getQueryFilter().clone();
|
||||
setInputValuesInQueryFilter(reportInput, queryFilter);
|
||||
|
||||
CountInput countInput = new CountInput();
|
||||
countInput.setTableName(dataSource.getSourceTable());
|
||||
countInput.setFilter(queryFilter);
|
||||
countInput.setQueryJoins(cloneDataSourceQueryJoins(dataSource));
|
||||
CountOutput countOutput = new CountAction().execute(countInput);
|
||||
|
||||
if(countOutput.getCount() != null)
|
||||
Integer count = null;
|
||||
if(dataSource.getCustomRecordSource() != null)
|
||||
{
|
||||
countByDataSource.put(dataSource.getName(), countOutput.getCount());
|
||||
// todo - add `count` method to interface?
|
||||
}
|
||||
else if(StringUtils.hasContent(dataSource.getSourceTable()))
|
||||
{
|
||||
QQueryFilter queryFilter = dataSource.getQueryFilter() == null ? new QQueryFilter() : dataSource.getQueryFilter().clone();
|
||||
setInputValuesInQueryFilter(reportInput, queryFilter);
|
||||
|
||||
if(reportFormat.getMaxRows() != null && countOutput.getCount() > reportFormat.getMaxRows())
|
||||
CountInput countInput = new CountInput();
|
||||
countInput.setTableName(dataSource.getSourceTable());
|
||||
countInput.setFilter(queryFilter);
|
||||
countInput.setQueryJoins(cloneDataSourceQueryJoins(dataSource));
|
||||
CountOutput countOutput = new CountAction().execute(countInput);
|
||||
|
||||
count = countOutput.getCount();
|
||||
}
|
||||
|
||||
if(count != null)
|
||||
{
|
||||
countByDataSource.put(dataSource.getName(), count);
|
||||
|
||||
if(reportFormat.getMaxRows() != null && count > reportFormat.getMaxRows())
|
||||
{
|
||||
throw (new QUserFacingException("The requested report would include more rows ("
|
||||
+ String.format("%,d", countOutput.getCount()) + ") than the maximum allowed ("
|
||||
+ String.format("%,d", count) + ") than the maximum allowed ("
|
||||
+ String.format("%,d", reportFormat.getMaxRows()) + ") for the selected file format (" + reportFormat + ")."));
|
||||
}
|
||||
}
|
||||
@ -423,13 +444,19 @@ public class GenerateReportAction extends AbstractQActionFunction<ReportInput, R
|
||||
String tableLabel = ObjectUtils.tryElse(() -> QContext.getQInstance().getTable(dataSource.getSourceTable()).getLabel(), Objects.requireNonNullElse(dataSource.getSourceTable(), ""));
|
||||
AtomicInteger consumedCount = new AtomicInteger(0);
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// run a record pipe loop, over the query for this data source //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// run a record pipe loop, over the query (or other data-supplier/source) for this data source //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
RecordPipe recordPipe = new BufferedRecordPipe(1000);
|
||||
new AsyncRecordPipeLoop().run("Report[" + reportInput.getReportName() + "]", null, recordPipe, (callback) ->
|
||||
{
|
||||
if(dataSource.getSourceTable() != null)
|
||||
if(dataSource.getCustomRecordSource() != null)
|
||||
{
|
||||
ReportCustomRecordSourceInterface recordSource = QCodeLoader.getAdHoc(ReportCustomRecordSourceInterface.class, dataSource.getCustomRecordSource());
|
||||
recordSource.execute(reportInput, dataSource, recordPipe);
|
||||
return (true);
|
||||
}
|
||||
else if(dataSource.getSourceTable() != null)
|
||||
{
|
||||
QQueryFilter queryFilter = dataSource.getQueryFilter() == null ? new QQueryFilter() : dataSource.getQueryFilter().clone();
|
||||
setInputValuesInQueryFilter(reportInput, queryFilter);
|
||||
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.actions.reporting.customizers;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.actions.reporting.RecordPipe;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportInput;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.reporting.QReportDataSource;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Interface to be implemented to do a custom source of data for a report
|
||||
** (instead of just a query against a table).
|
||||
*******************************************************************************/
|
||||
public interface ReportCustomRecordSourceInterface
|
||||
{
|
||||
|
||||
/***************************************************************************
|
||||
** Given the report input, put records into the pipe, for the report.
|
||||
***************************************************************************/
|
||||
void execute(ReportInput reportInput, QReportDataSource reportDataSource, RecordPipe recordPipe) throws QException;
|
||||
|
||||
}
|
@ -124,7 +124,7 @@ public class ExcelFastexcelExportStreamer implements ExportStreamerInterface
|
||||
if(workbook == null)
|
||||
{
|
||||
String appName = ObjectUtils.tryAndRequireNonNullElse(() -> QContext.getQInstance().getBranding().getAppName(), "QQQ");
|
||||
QInstance instance = exportInput.getInstance();
|
||||
QInstance instance = QContext.getQInstance();
|
||||
if(instance != null && instance.getBranding() != null && instance.getBranding().getCompanyName() != null)
|
||||
{
|
||||
appName = instance.getBranding().getCompanyName();
|
||||
|
@ -124,10 +124,11 @@ public class ExcelPoiBasedStreamingExportStreamer implements ExportStreamerInter
|
||||
private Writer activeSheetWriter = null;
|
||||
private StreamedSheetWriter sheetWriter = null;
|
||||
|
||||
private QReportView currentView = null;
|
||||
private Map<String, List<QFieldMetaData>> fieldsPerView = new HashMap<>();
|
||||
private Map<String, Integer> rowsPerView = new HashMap<>();
|
||||
private Map<String, String> labelViewsByName = new HashMap<>();
|
||||
private QReportView currentView = null;
|
||||
private Map<String, List<QFieldMetaData>> fieldsPerView = new HashMap<>();
|
||||
private Map<String, Integer> rowsPerView = new HashMap<>();
|
||||
private Map<String, String> labelViewsByName = new HashMap<>();
|
||||
private Map<String, String> sheetReferenceByViewName = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
@ -180,6 +181,7 @@ public class ExcelPoiBasedStreamingExportStreamer implements ExportStreamerInter
|
||||
String sheetReference = sheet.getPackagePart().getPartName().getName().substring(1);
|
||||
sheetMapByExcelReference.put(sheetReference, sheet);
|
||||
sheetMapByViewName.put(view.getName(), sheet);
|
||||
sheetReferenceByViewName.put(view.getName(), sheetReference);
|
||||
sheetCounter++;
|
||||
}
|
||||
|
||||
@ -446,7 +448,7 @@ public class ExcelPoiBasedStreamingExportStreamer implements ExportStreamerInter
|
||||
// - with a new output stream writer //
|
||||
// - and with a SpreadsheetWriter //
|
||||
//////////////////////////////////////////
|
||||
zipOutputStream.putNextEntry(new ZipEntry("xl/worksheets/sheet" + this.sheetIndex++ + ".xml"));
|
||||
zipOutputStream.putNextEntry(new ZipEntry(sheetReferenceByViewName.get(view.getName())));
|
||||
activeSheetWriter = new OutputStreamWriter(zipOutputStream);
|
||||
sheetWriter = new StreamedSheetWriter(activeSheetWriter);
|
||||
|
||||
|
@ -161,7 +161,7 @@ public class StreamedSheetWriter
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Integer> m = new HashMap();
|
||||
Map<String, Integer> m = new HashMap<>();
|
||||
m.computeIfAbsent("s", (s) -> 3);
|
||||
|
||||
value = rs.toString();
|
||||
|
@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.core.actions.scripts;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.scripts.logging.BuildScriptLogAndScriptLogLineExecutionLogger;
|
||||
@ -97,7 +98,7 @@ public class RecordScriptTestInterface implements TestScriptActionInterface
|
||||
}
|
||||
|
||||
QueryOutput queryOutput = new QueryAction().execute(new QueryInput(tableName)
|
||||
.withFilter(new QQueryFilter(new QFilterCriteria(table.getPrimaryKeyField(), QCriteriaOperator.IN, recordPrimaryKeyList.split(","))))
|
||||
.withFilter(new QQueryFilter(new QFilterCriteria(table.getPrimaryKeyField(), QCriteriaOperator.IN, Arrays.stream(recordPrimaryKeyList.split(",")).toList())))
|
||||
.withIncludeAssociations(true));
|
||||
if(CollectionUtils.nullSafeIsEmpty(queryOutput.getRecords()))
|
||||
{
|
||||
|
@ -154,8 +154,9 @@ public class RunAdHocRecordScriptAction
|
||||
Method qRecordListToApiRecordList = apiScriptUtilsClass.getMethod("qRecordListToApiRecordList", List.class, String.class, String.class, String.class);
|
||||
Object apiRecordList = qRecordListToApiRecordList.invoke(null, input.getRecordList(), input.getTableName(), scriptRevision.getApiName(), scriptRevision.getApiVersion());
|
||||
|
||||
// noinspection unchecked
|
||||
return (ArrayList<? extends Serializable>) apiRecordList;
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<? extends Serializable> rs = (ArrayList<? extends Serializable>) apiRecordList;
|
||||
return rs;
|
||||
}
|
||||
catch(ClassNotFoundException e)
|
||||
{
|
||||
|
@ -352,7 +352,7 @@ public class GetAction
|
||||
{
|
||||
if(qPossibleValueTranslator == null)
|
||||
{
|
||||
qPossibleValueTranslator = new QPossibleValueTranslator(getInput.getInstance(), getInput.getSession());
|
||||
qPossibleValueTranslator = new QPossibleValueTranslator(QContext.getQInstance(), QContext.getQSession());
|
||||
}
|
||||
qPossibleValueTranslator.translatePossibleValuesInRecords(getInput.getTable(), List.of(returnRecord));
|
||||
}
|
||||
|
@ -227,6 +227,11 @@ public class InsertAction extends AbstractQActionFunction<InsertInput, InsertOut
|
||||
*******************************************************************************/
|
||||
public void performValidations(InsertInput insertInput, boolean isPreview) throws QException
|
||||
{
|
||||
if(CollectionUtils.nullSafeIsEmpty(insertInput.getRecords()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QTableMetaData table = insertInput.getTable();
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
@ -241,7 +246,7 @@ public class InsertAction extends AbstractQActionFunction<InsertInput, InsertOut
|
||||
|
||||
setDefaultValuesInRecords(table, insertInput.getRecords());
|
||||
|
||||
ValueBehaviorApplier.applyFieldBehaviors(ValueBehaviorApplier.Action.INSERT, insertInput.getInstance(), table, insertInput.getRecords(), null);
|
||||
ValueBehaviorApplier.applyFieldBehaviors(ValueBehaviorApplier.Action.INSERT, QContext.getQInstance(), table, insertInput.getRecords(), null);
|
||||
|
||||
runPreInsertCustomizerIfItIsTime(insertInput, isPreview, preInsertCustomizer, AbstractPreInsertCustomizer.WhenToRun.BEFORE_UNIQUE_KEY_CHECKS);
|
||||
setErrorsIfUniqueKeyErrors(insertInput, table);
|
||||
|
@ -26,6 +26,7 @@ import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -50,6 +51,7 @@ import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperat
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QFilterCriteria;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QQueryFilter;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryJoin;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
||||
@ -64,6 +66,7 @@ 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 com.kingsrook.qqq.backend.core.utils.ListingHash;
|
||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||
|
||||
|
||||
@ -101,6 +104,8 @@ public class QueryAction
|
||||
throw (new QException("A table named [" + queryInput.getTableName() + "] was not found in the active QInstance"));
|
||||
}
|
||||
|
||||
validateFieldNamesToInclude(queryInput);
|
||||
|
||||
QBackendMetaData backend = queryInput.getBackend();
|
||||
postQueryRecordCustomizer = QCodeLoader.getTableCustomizer(table, TableCustomizers.POST_QUERY_RECORD.getRole());
|
||||
this.queryInput = queryInput;
|
||||
@ -158,6 +163,109 @@ public class QueryAction
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** if QueryInput contains a set of FieldNamesToInclude, then validate that
|
||||
** those are known field names in the table being queried, or a selected
|
||||
** queryJoin.
|
||||
***************************************************************************/
|
||||
static void validateFieldNamesToInclude(QueryInput queryInput) throws QException
|
||||
{
|
||||
Set<String> fieldNamesToInclude = queryInput.getFieldNamesToInclude();
|
||||
if(fieldNamesToInclude == null)
|
||||
{
|
||||
////////////////////////////////
|
||||
// null set means select all. //
|
||||
////////////////////////////////
|
||||
return;
|
||||
}
|
||||
|
||||
if(fieldNamesToInclude.isEmpty())
|
||||
{
|
||||
/////////////////////////////////////
|
||||
// empty set, however, is an error //
|
||||
/////////////////////////////////////
|
||||
throw (new QException("An empty set of fieldNamesToInclude was given as queryInput, which is not allowed."));
|
||||
}
|
||||
|
||||
List<String> unrecognizedFieldNames = new ArrayList<>();
|
||||
Map<String, QTableMetaData> selectedQueryJoins = null;
|
||||
for(String fieldName : fieldNamesToInclude)
|
||||
{
|
||||
if(fieldName.contains("."))
|
||||
{
|
||||
////////////////////////////////////////////////
|
||||
// handle names with dots - fields from joins //
|
||||
////////////////////////////////////////////////
|
||||
String[] parts = fieldName.split("\\.");
|
||||
if(parts.length != 2)
|
||||
{
|
||||
unrecognizedFieldNames.add(fieldName);
|
||||
}
|
||||
else
|
||||
{
|
||||
String tableOrAlias = parts[0];
|
||||
String fieldNamePart = parts[1];
|
||||
|
||||
////////////////////////////////////////////
|
||||
// build map of queryJoins being selected //
|
||||
////////////////////////////////////////////
|
||||
if(selectedQueryJoins == null)
|
||||
{
|
||||
selectedQueryJoins = new HashMap<>();
|
||||
for(QueryJoin queryJoin : CollectionUtils.nonNullList(queryInput.getQueryJoins()))
|
||||
{
|
||||
if(queryJoin.getSelect())
|
||||
{
|
||||
String joinTableOrAlias = queryJoin.getJoinTableOrItsAlias();
|
||||
QTableMetaData joinTable = QContext.getQInstance().getTable(queryJoin.getJoinTable());
|
||||
if(joinTable != null)
|
||||
{
|
||||
selectedQueryJoins.put(joinTableOrAlias, joinTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!selectedQueryJoins.containsKey(tableOrAlias))
|
||||
{
|
||||
///////////////////////////////////////////
|
||||
// unrecognized tableOrAlias is an error //
|
||||
///////////////////////////////////////////
|
||||
unrecognizedFieldNames.add(fieldName);
|
||||
}
|
||||
else
|
||||
{
|
||||
QTableMetaData joinTable = selectedQueryJoins.get(tableOrAlias);
|
||||
if(!joinTable.getFields().containsKey(fieldNamePart))
|
||||
{
|
||||
//////////////////////////////////////////////////////////
|
||||
// unrecognized field within the join table is an error //
|
||||
//////////////////////////////////////////////////////////
|
||||
unrecognizedFieldNames.add(fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// non-join fields - just ensure field name is in table's fields map //
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
if(!queryInput.getTable().getFields().containsKey(fieldName))
|
||||
{
|
||||
unrecognizedFieldNames.add(fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!unrecognizedFieldNames.isEmpty())
|
||||
{
|
||||
throw (new QException("QueryInput contained " + unrecognizedFieldNames.size() + " unrecognized field name" + StringUtils.plural(unrecognizedFieldNames) + ": " + StringUtils.join(",", unrecognizedFieldNames)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** shorthand way to call for the most common use-case, when you just want the
|
||||
** records to be returned, and you just want to pass in a table name and filter.
|
||||
@ -297,7 +405,7 @@ public class QueryAction
|
||||
{
|
||||
if(qPossibleValueTranslator == null)
|
||||
{
|
||||
qPossibleValueTranslator = new QPossibleValueTranslator(queryInput.getInstance(), queryInput.getSession());
|
||||
qPossibleValueTranslator = new QPossibleValueTranslator(QContext.getQInstance(), QContext.getQSession());
|
||||
}
|
||||
qPossibleValueTranslator.translatePossibleValuesInRecords(queryInput.getTable(), records, queryInput.getQueryJoins(), queryInput.getFieldsToTranslatePossibleValues());
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ public class UpdateAction
|
||||
behaviorsToOmit = Set.of(DynamicDefaultValueBehavior.MODIFY_DATE);
|
||||
}
|
||||
|
||||
ValueBehaviorApplier.applyFieldBehaviors(ValueBehaviorApplier.Action.UPDATE, updateInput.getInstance(), table, updateInput.getRecords(), behaviorsToOmit);
|
||||
ValueBehaviorApplier.applyFieldBehaviors(ValueBehaviorApplier.Action.UPDATE, QContext.getQInstance(), table, updateInput.getRecords(), behaviorsToOmit);
|
||||
validatePrimaryKeysAreGiven(updateInput);
|
||||
|
||||
if(oldRecordList.isPresent())
|
||||
|
@ -68,7 +68,7 @@ public class QValueFormatter
|
||||
*******************************************************************************/
|
||||
public static String formatValue(QFieldMetaData field, Serializable value)
|
||||
{
|
||||
return (formatValue(field.getDisplayFormat(), field.getName(), value));
|
||||
return (formatValue(field.getDisplayFormat(), field.getType(), field.getName(), value));
|
||||
}
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ public class QValueFormatter
|
||||
*******************************************************************************/
|
||||
public static String formatValue(String displayFormat, Serializable value)
|
||||
{
|
||||
return (formatValue(displayFormat, "", value));
|
||||
return (formatValue(displayFormat, null, "", value));
|
||||
}
|
||||
|
||||
|
||||
@ -87,7 +87,7 @@ public class QValueFormatter
|
||||
** For a display format string, an optional fieldName (only used for logging),
|
||||
** and a value, apply the format.
|
||||
*******************************************************************************/
|
||||
private static String formatValue(String displayFormat, String fieldName, Serializable value)
|
||||
private static String formatValue(String displayFormat, QFieldType fieldType, String fieldName, Serializable value)
|
||||
{
|
||||
//////////////////////////////////
|
||||
// null values get null results //
|
||||
@ -107,6 +107,11 @@ public class QValueFormatter
|
||||
return formatBoolean(b);
|
||||
}
|
||||
|
||||
if(QFieldType.BOOLEAN.equals(fieldType))
|
||||
{
|
||||
return formatBoolean(ValueUtils.getValueAsBoolean(value));
|
||||
}
|
||||
|
||||
if(value instanceof LocalTime lt)
|
||||
{
|
||||
return formatLocalTime(lt);
|
||||
@ -404,6 +409,7 @@ public class QValueFormatter
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** For a single record, set its display values - where caller (meant to stay private)
|
||||
** can specify if they've already done fieldBehaviors (to avoid re-doing).
|
||||
@ -563,6 +569,7 @@ public class QValueFormatter
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// heavy fields that weren't fetched - they should have a backend-detail specifying their length (or null if null) //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Serializable> heavyFieldLengths = (Map<String, Serializable>) record.getBackendDetail(QRecord.BACKEND_DETAILS_TYPE_HEAVY_FIELD_LENGTHS);
|
||||
if(heavyFieldLengths != null)
|
||||
{
|
||||
|
@ -30,6 +30,7 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QCriteriaOperator;
|
||||
@ -69,14 +70,14 @@ public class SearchPossibleValueSourceAction
|
||||
*******************************************************************************/
|
||||
public SearchPossibleValueSourceOutput execute(SearchPossibleValueSourceInput input) throws QException
|
||||
{
|
||||
QInstance qInstance = input.getInstance();
|
||||
QInstance qInstance = QContext.getQInstance();
|
||||
QPossibleValueSource possibleValueSource = qInstance.getPossibleValueSource(input.getPossibleValueSourceName());
|
||||
if(possibleValueSource == null)
|
||||
{
|
||||
throw new QException("Missing possible value source named [" + input.getPossibleValueSourceName() + "]");
|
||||
}
|
||||
|
||||
possibleValueTranslator = new QPossibleValueTranslator(input.getInstance(), input.getSession());
|
||||
possibleValueTranslator = new QPossibleValueTranslator(QContext.getQInstance(), QContext.getQSession());
|
||||
SearchPossibleValueSourceOutput output = null;
|
||||
if(possibleValueSource.getType().equals(QPossibleValueSourceType.ENUM))
|
||||
{
|
||||
@ -199,7 +200,7 @@ public class SearchPossibleValueSourceAction
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName(possibleValueSource.getTableName());
|
||||
|
||||
QTableMetaData table = input.getInstance().getTable(possibleValueSource.getTableName());
|
||||
QTableMetaData table = QContext.getQInstance().getTable(possibleValueSource.getTableName());
|
||||
|
||||
QQueryFilter queryFilter = new QQueryFilter();
|
||||
queryFilter.setBooleanOperator(QQueryFilter.BooleanOperator.OR);
|
||||
@ -299,6 +300,7 @@ public class SearchPossibleValueSourceAction
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private SearchPossibleValueSourceOutput searchPossibleValueCustom(SearchPossibleValueSourceInput input, QPossibleValueSource possibleValueSource)
|
||||
{
|
||||
try
|
||||
|
@ -22,8 +22,8 @@
|
||||
package com.kingsrook.qqq.backend.core.exceptions;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||
|
||||
|
||||
@ -55,12 +55,11 @@ public class QInstanceValidationException extends QException
|
||||
*******************************************************************************/
|
||||
public QInstanceValidationException(List<String> reasons)
|
||||
{
|
||||
super(
|
||||
(reasons != null && reasons.size() > 0)
|
||||
? "Instance validation failed for the following reasons:\n - " + StringUtils.join("\n - ", reasons)
|
||||
: "Validation failed, but no reasons were provided");
|
||||
super((CollectionUtils.nullSafeHasContents(reasons))
|
||||
? "Instance validation failed for the following reasons:\n - " + StringUtils.join("\n - ", reasons) + "\n(" + reasons.size() + " Total reason" + StringUtils.plural(reasons) + ")"
|
||||
: "Validation failed, but no reasons were provided");
|
||||
|
||||
if(reasons != null && reasons.size() > 0)
|
||||
if(CollectionUtils.nullSafeHasContents(reasons))
|
||||
{
|
||||
this.reasons = reasons;
|
||||
}
|
||||
@ -68,25 +67,6 @@ public class QInstanceValidationException extends QException
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor of an array/varargs of reasons. They feed into the core exception message.
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QInstanceValidationException(String... reasons)
|
||||
{
|
||||
super(
|
||||
(reasons != null && reasons.length > 0)
|
||||
? "Instance validation failed for the following reasons: " + StringUtils.joinWithCommasAndAnd(Arrays.stream(reasons).toList())
|
||||
: "Validation failed, but no reasons were provided");
|
||||
|
||||
if(reasons != null && reasons.length > 0)
|
||||
{
|
||||
this.reasons = Arrays.stream(reasons).toList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor of message & cause - does not populate reasons!
|
||||
**
|
||||
|
@ -44,6 +44,7 @@ import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers;
|
||||
import com.kingsrook.qqq.backend.core.actions.dashboard.widgets.AbstractWidgetRenderer;
|
||||
import com.kingsrook.qqq.backend.core.actions.metadata.JoinGraph;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.actions.reporting.customizers.ReportCustomRecordSourceInterface;
|
||||
import com.kingsrook.qqq.backend.core.actions.scripts.TestScriptActionInterface;
|
||||
import com.kingsrook.qqq.backend.core.actions.values.QCustomPossibleValueProvider;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
||||
@ -922,7 +923,7 @@ public class QInstanceValidator
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private <T extends FieldBehavior<T>> void validateTableField(QInstance qInstance, String tableName, String fieldName, QTableMetaData table, QFieldMetaData field)
|
||||
private void validateTableField(QInstance qInstance, String tableName, String fieldName, QTableMetaData table, QFieldMetaData field)
|
||||
{
|
||||
assertCondition(Objects.equals(fieldName, field.getName()),
|
||||
"Inconsistent naming in table " + tableName + " for field " + fieldName + "/" + field.getName() + ".");
|
||||
@ -944,12 +945,13 @@ public class QInstanceValidator
|
||||
assertCondition(field.getMaxLength() != null, prefix + "specifies a ValueTooLongBehavior, but not a maxLength.");
|
||||
}
|
||||
|
||||
Set<Class<FieldBehavior<T>>> usedFieldBehaviorTypes = new HashSet<>();
|
||||
Set<Class<FieldBehavior<?>>> usedFieldBehaviorTypes = new HashSet<>();
|
||||
if(field.getBehaviors() != null)
|
||||
{
|
||||
for(FieldBehavior<?> fieldBehavior : field.getBehaviors())
|
||||
{
|
||||
Class<FieldBehavior<T>> behaviorClass = (Class<FieldBehavior<T>>) fieldBehavior.getClass();
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<FieldBehavior<?>> behaviorClass = (Class<FieldBehavior<?>>) fieldBehavior.getClass();
|
||||
|
||||
errors.addAll(fieldBehavior.validateBehaviorConfiguration(table, field));
|
||||
|
||||
@ -1659,9 +1661,12 @@ public class QInstanceValidator
|
||||
|
||||
String dataSourceErrorPrefix = "Report " + reportName + " data source " + dataSource.getName() + " ";
|
||||
|
||||
boolean hasASource = false;
|
||||
|
||||
if(StringUtils.hasContent(dataSource.getSourceTable()))
|
||||
{
|
||||
assertCondition(dataSource.getStaticDataSupplier() == null, dataSourceErrorPrefix + "has both a sourceTable and a staticDataSupplier (exactly 1 is required).");
|
||||
hasASource = true;
|
||||
assertCondition(dataSource.getStaticDataSupplier() == null, dataSourceErrorPrefix + "has both a sourceTable and a staticDataSupplier (not compatible together).");
|
||||
if(assertCondition(qInstance.getTable(dataSource.getSourceTable()) != null, dataSourceErrorPrefix + "source table " + dataSource.getSourceTable() + " is not a table in this instance."))
|
||||
{
|
||||
if(dataSource.getQueryFilter() != null)
|
||||
@ -1670,14 +1675,21 @@ public class QInstanceValidator
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(dataSource.getStaticDataSupplier() != null)
|
||||
|
||||
if(dataSource.getStaticDataSupplier() != null)
|
||||
{
|
||||
assertCondition(dataSource.getCustomRecordSource() == null, dataSourceErrorPrefix + "has both a staticDataSupplier and a customRecordSource (not compatible together).");
|
||||
hasASource = true;
|
||||
validateSimpleCodeReference(dataSourceErrorPrefix, dataSource.getStaticDataSupplier(), Supplier.class);
|
||||
}
|
||||
else
|
||||
|
||||
if(dataSource.getCustomRecordSource() != null)
|
||||
{
|
||||
errors.add(dataSourceErrorPrefix + "does not have a sourceTable or a staticDataSupplier (exactly 1 is required).");
|
||||
hasASource = true;
|
||||
validateSimpleCodeReference(dataSourceErrorPrefix, dataSource.getCustomRecordSource(), ReportCustomRecordSourceInterface.class);
|
||||
}
|
||||
|
||||
assertCondition(hasASource, dataSourceErrorPrefix + "does not have a sourceTable, customRecordSource, or a staticDataSupplier.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.core.instances;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
@ -113,7 +114,7 @@ public class SecretsManagerUtils
|
||||
dotEnv.renameTo(new File(".env.backup-" + System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
FileUtils.writeStringToFile(dotEnv, fullEnv.toString());
|
||||
FileUtils.writeStringToFile(dotEnv, fullEnv.toString(), StandardCharsets.UTF_8);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -32,7 +32,6 @@ import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
||||
import com.kingsrook.qqq.backend.core.instances.QInstanceValidator;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.authentication.QAuthenticationMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
|
||||
|
||||
@ -93,17 +92,6 @@ public class AbstractActionInput
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@JsonIgnore
|
||||
public QAuthenticationMetaData getAuthenticationMetaData()
|
||||
{
|
||||
return (getInstance().getAuthentication());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for instance
|
||||
**
|
||||
|
@ -152,5 +152,8 @@ public class AuditDetailAccumulator implements Serializable
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
private record TableNameAndPrimaryKey(String tableName, Serializable primaryKey) {}
|
||||
}
|
||||
|
@ -59,6 +59,30 @@ public class AggregateInput extends AbstractTableActionInput
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor
|
||||
**
|
||||
*******************************************************************************/
|
||||
public AggregateInput(String tableName)
|
||||
{
|
||||
this();
|
||||
setTableName(tableName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public AggregateInput withTableName(String tableName)
|
||||
{
|
||||
super.withTableName(tableName);
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for filter
|
||||
**
|
||||
|
@ -66,6 +66,14 @@ public class QueryInput extends AbstractTableActionInput implements QueryOrGetIn
|
||||
private List<QueryJoin> queryJoins = null;
|
||||
private boolean selectDistinct = false;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// if this set is null, then the default (all fields) should be included //
|
||||
// if it's an empty set, that should throw an error //
|
||||
// or if there are any fields in it that aren't valid fields on the table, //
|
||||
// or in a selected queryJoin. //
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
private Set<String> fieldNamesToInclude;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if you say you want to includeAssociations, you can limit which ones by passing them in associationNamesToInclude. //
|
||||
// if you leave it null, you get all associations defined on the table. if you pass it as empty, you get none. //
|
||||
@ -686,4 +694,35 @@ public class QueryInput extends AbstractTableActionInput implements QueryOrGetIn
|
||||
return (queryHints.contains(queryHint));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for fieldNamesToInclude
|
||||
*******************************************************************************/
|
||||
public Set<String> getFieldNamesToInclude()
|
||||
{
|
||||
return (this.fieldNamesToInclude);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for fieldNamesToInclude
|
||||
*******************************************************************************/
|
||||
public void setFieldNamesToInclude(Set<String> fieldNamesToInclude)
|
||||
{
|
||||
this.fieldNamesToInclude = fieldNamesToInclude;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for fieldNamesToInclude
|
||||
*******************************************************************************/
|
||||
public QueryInput withFieldNamesToInclude(Set<String> fieldNamesToInclude)
|
||||
{
|
||||
this.fieldNamesToInclude = fieldNamesToInclude;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -40,11 +40,14 @@ public abstract class AbstractFilterExpression<T extends Serializable> implement
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Evaluate the expression, given a map of input values.
|
||||
**
|
||||
** By default, this will defer to the evaluate(void) method - but, a subclass
|
||||
** (e.g., FilterVariableExpression) may react differently.
|
||||
*******************************************************************************/
|
||||
public T evaluateInputValues(Map<String, Serializable> inputValues) throws QException
|
||||
{
|
||||
return (T) this;
|
||||
return evaluate();
|
||||
}
|
||||
|
||||
|
||||
|
@ -42,6 +42,9 @@ public class NowWithOffset extends AbstractFilterExpression<Instant>
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public enum Operator
|
||||
{PLUS, MINUS}
|
||||
|
||||
|
@ -43,6 +43,9 @@ public class ThisOrLastPeriod extends AbstractFilterExpression<Instant>
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public enum Operator
|
||||
{THIS, LAST}
|
||||
|
||||
|
@ -79,10 +79,11 @@ public class QFilterCriteriaDeserializer extends StdDeserializer<QFilterCriteria
|
||||
/////////////////////////////////
|
||||
// get values out of json node //
|
||||
/////////////////////////////////
|
||||
List<Serializable> values = objectMapper.treeToValue(node.get("values"), List.class);
|
||||
String fieldName = objectMapper.treeToValue(node.get("fieldName"), String.class);
|
||||
QCriteriaOperator operator = objectMapper.treeToValue(node.get("operator"), QCriteriaOperator.class);
|
||||
String otherFieldName = objectMapper.treeToValue(node.get("otherFieldName"), String.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Serializable> values = objectMapper.treeToValue(node.get("values"), List.class);
|
||||
String fieldName = objectMapper.treeToValue(node.get("fieldName"), String.class);
|
||||
QCriteriaOperator operator = objectMapper.treeToValue(node.get("operator"), QCriteriaOperator.class);
|
||||
String otherFieldName = objectMapper.treeToValue(node.get("otherFieldName"), String.class);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// look at all the values - if any of them are actually meant to be an Expression (instance of subclass of AbstractFilterExpression) //
|
||||
|
@ -28,6 +28,9 @@ package com.kingsrook.qqq.backend.core.model.dashboard.widgets;
|
||||
*******************************************************************************/
|
||||
public class AlertData extends QWidgetData
|
||||
{
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public enum AlertType
|
||||
{
|
||||
ERROR,
|
||||
|
@ -40,9 +40,10 @@ public class CompositeWidgetData extends AbstractBlockWidgetData<CompositeWidget
|
||||
{
|
||||
private List<AbstractBlockWidgetData<?, ?, ?, ?>> blocks = new ArrayList<>();
|
||||
|
||||
private Map<String, Serializable> styleOverrides = new HashMap<>();
|
||||
|
||||
private Layout layout;
|
||||
private Layout layout;
|
||||
private Map<String, Serializable> styleOverrides = new HashMap<>();
|
||||
private String overlayHtml;
|
||||
private Map<String, Serializable> overlayStyleOverrides = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
@ -218,4 +219,91 @@ public class CompositeWidgetData extends AbstractBlockWidgetData<CompositeWidget
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for overlayHtml
|
||||
*******************************************************************************/
|
||||
public String getOverlayHtml()
|
||||
{
|
||||
return (this.overlayHtml);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for overlayHtml
|
||||
*******************************************************************************/
|
||||
public void setOverlayHtml(String overlayHtml)
|
||||
{
|
||||
this.overlayHtml = overlayHtml;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for overlayHtml
|
||||
*******************************************************************************/
|
||||
public CompositeWidgetData withOverlayHtml(String overlayHtml)
|
||||
{
|
||||
this.overlayHtml = overlayHtml;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for overlayStyleOverrides
|
||||
*******************************************************************************/
|
||||
public Map<String, Serializable> getOverlayStyleOverrides()
|
||||
{
|
||||
return (this.overlayStyleOverrides);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for overlayStyleOverrides
|
||||
*******************************************************************************/
|
||||
public void setOverlayStyleOverrides(Map<String, Serializable> overlayStyleOverrides)
|
||||
{
|
||||
this.overlayStyleOverrides = overlayStyleOverrides;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for overlayStyleOverrides
|
||||
*******************************************************************************/
|
||||
public CompositeWidgetData withOverlayStyleOverrides(Map<String, Serializable> overlayStyleOverrides)
|
||||
{
|
||||
this.overlayStyleOverrides = overlayStyleOverrides;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public CompositeWidgetData withOverlayStyleOverride(String key, Serializable value)
|
||||
{
|
||||
addOverlayStyleOverride(key, value);
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void addOverlayStyleOverride(String key, Serializable value)
|
||||
{
|
||||
if(this.overlayStyleOverrides == null)
|
||||
{
|
||||
this.overlayStyleOverrides = new HashMap<>();
|
||||
}
|
||||
this.overlayStyleOverrides.put(key, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.CompositeWidgetData;
|
||||
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.QWidgetData;
|
||||
|
||||
|
||||
@ -74,6 +75,7 @@ public abstract class AbstractBlockWidgetData<
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withTooltip(S key, String value)
|
||||
{
|
||||
addTooltip(key, value);
|
||||
@ -99,6 +101,7 @@ public abstract class AbstractBlockWidgetData<
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withTooltip(S key, BlockTooltip value)
|
||||
{
|
||||
addTooltip(key, value);
|
||||
@ -144,6 +147,7 @@ public abstract class AbstractBlockWidgetData<
|
||||
/*******************************************************************************
|
||||
** Fluent setter for tooltipMap
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withTooltipMap(Map<S, BlockTooltip> tooltipMap)
|
||||
{
|
||||
this.tooltipMap = tooltipMap;
|
||||
@ -178,6 +182,7 @@ public abstract class AbstractBlockWidgetData<
|
||||
** Fluent setter for tooltip
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withTooltip(String tooltip)
|
||||
{
|
||||
this.tooltip = new BlockTooltip(tooltip);
|
||||
@ -190,6 +195,7 @@ public abstract class AbstractBlockWidgetData<
|
||||
** Fluent setter for tooltip
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withTooltip(BlockTooltip tooltip)
|
||||
{
|
||||
this.tooltip = tooltip;
|
||||
@ -199,8 +205,22 @@ public abstract class AbstractBlockWidgetData<
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for tooltip
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withTooltip(CompositeWidgetData data)
|
||||
{
|
||||
this.tooltip = new BlockTooltip(data);
|
||||
return (T) (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withLink(S key, String value)
|
||||
{
|
||||
addLink(key, value);
|
||||
@ -226,6 +246,7 @@ public abstract class AbstractBlockWidgetData<
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withLink(S key, BlockLink value)
|
||||
{
|
||||
addLink(key, value);
|
||||
@ -271,6 +292,7 @@ public abstract class AbstractBlockWidgetData<
|
||||
/*******************************************************************************
|
||||
** Fluent setter for linkMap
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withLinkMap(Map<S, BlockLink> linkMap)
|
||||
{
|
||||
this.linkMap = linkMap;
|
||||
@ -305,6 +327,7 @@ public abstract class AbstractBlockWidgetData<
|
||||
** Fluent setter for link
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withLink(String link)
|
||||
{
|
||||
this.link = new BlockLink(link);
|
||||
@ -317,6 +340,7 @@ public abstract class AbstractBlockWidgetData<
|
||||
** Fluent setter for link
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withLink(BlockLink link)
|
||||
{
|
||||
this.link = link;
|
||||
@ -348,6 +372,7 @@ public abstract class AbstractBlockWidgetData<
|
||||
/*******************************************************************************
|
||||
** Fluent setter for values
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withValues(V values)
|
||||
{
|
||||
this.values = values;
|
||||
@ -379,6 +404,7 @@ public abstract class AbstractBlockWidgetData<
|
||||
/*******************************************************************************
|
||||
** Fluent setter for styles
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withStyles(SX styles)
|
||||
{
|
||||
this.styles = styles;
|
||||
@ -386,6 +412,7 @@ public abstract class AbstractBlockWidgetData<
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for blockId
|
||||
*******************************************************************************/
|
||||
@ -409,11 +436,11 @@ public abstract class AbstractBlockWidgetData<
|
||||
/*******************************************************************************
|
||||
** Fluent setter for blockId
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T withBlockId(String blockId)
|
||||
{
|
||||
this.blockId = blockId;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -22,17 +22,24 @@
|
||||
package com.kingsrook.qqq.backend.core.model.dashboard.widgets.blocks;
|
||||
|
||||
|
||||
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.CompositeWidgetData;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** A tooltip used within a (widget) block.
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class BlockTooltip
|
||||
{
|
||||
private String title;
|
||||
private Placement placement = Placement.BOTTOM;
|
||||
private CompositeWidgetData blockData;
|
||||
private String title;
|
||||
private Placement placement = Placement.BOTTOM;
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public enum Placement
|
||||
{BOTTOM, LEFT, RIGHT, TOP}
|
||||
|
||||
@ -59,6 +66,17 @@ public class BlockTooltip
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor
|
||||
**
|
||||
*******************************************************************************/
|
||||
public BlockTooltip(CompositeWidgetData blockData)
|
||||
{
|
||||
this.blockData = blockData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for title
|
||||
*******************************************************************************/
|
||||
@ -119,4 +137,35 @@ public class BlockTooltip
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for blockData
|
||||
*******************************************************************************/
|
||||
public CompositeWidgetData getBlockData()
|
||||
{
|
||||
return (this.blockData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for blockData
|
||||
*******************************************************************************/
|
||||
public void setBlockData(CompositeWidgetData blockData)
|
||||
{
|
||||
this.blockData = blockData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for blockData
|
||||
*******************************************************************************/
|
||||
public BlockTooltip withBlockData(CompositeWidgetData blockData)
|
||||
{
|
||||
this.blockData = blockData;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -192,6 +192,7 @@ public abstract class QRecordEntity
|
||||
|
||||
for(QRecordEntityAssociation qRecordEntityAssociation : getAssociationList(this.getClass()))
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
List<? extends QRecordEntity> associatedEntities = (List<? extends QRecordEntity>) qRecordEntityAssociation.getGetter().invoke(this);
|
||||
String associationName = qRecordEntityAssociation.getAssociationAnnotation().name();
|
||||
|
||||
@ -245,6 +246,7 @@ public abstract class QRecordEntity
|
||||
|
||||
for(QRecordEntityAssociation qRecordEntityAssociation : getAssociationList(this.getClass()))
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
List<? extends QRecordEntity> associatedEntities = (List<? extends QRecordEntity>) qRecordEntityAssociation.getGetter().invoke(this);
|
||||
String associationName = qRecordEntityAssociation.getAssociationAnnotation().name();
|
||||
|
||||
@ -346,6 +348,7 @@ public abstract class QRecordEntity
|
||||
|
||||
if(associationAnnotation.isPresent())
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends QRecordEntity> listTypeParam = (Class<? extends QRecordEntity>) getListTypeParam(possibleGetter.getReturnType(), possibleGetter.getAnnotatedReturnType());
|
||||
associationList.add(new QRecordEntityAssociation(fieldName, possibleGetter, setter.get(), listTypeParam, associationAnnotation.orElse(null)));
|
||||
}
|
||||
|
@ -53,6 +53,8 @@ public class QBackendMetaData implements TopLevelMetaDataInterface
|
||||
private String variantOptionsTableUsernameField;
|
||||
private String variantOptionsTablePasswordField;
|
||||
private String variantOptionsTableApiKeyField;
|
||||
private String variantOptionsTableClientIdField;
|
||||
private String variantOptionsTableClientSecretField;
|
||||
private String variantOptionsTableName;
|
||||
|
||||
// todo - at some point, we may want to apply this to secret properties on subclasses?
|
||||
@ -648,4 +650,66 @@ public class QBackendMetaData implements TopLevelMetaDataInterface
|
||||
{
|
||||
qInstance.addBackend(this);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for variantOptionsTableClientIdField
|
||||
*******************************************************************************/
|
||||
public String getVariantOptionsTableClientIdField()
|
||||
{
|
||||
return (this.variantOptionsTableClientIdField);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for variantOptionsTableClientIdField
|
||||
*******************************************************************************/
|
||||
public void setVariantOptionsTableClientIdField(String variantOptionsTableClientIdField)
|
||||
{
|
||||
this.variantOptionsTableClientIdField = variantOptionsTableClientIdField;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for variantOptionsTableClientIdField
|
||||
*******************************************************************************/
|
||||
public QBackendMetaData withVariantOptionsTableClientIdField(String variantOptionsTableClientIdField)
|
||||
{
|
||||
this.variantOptionsTableClientIdField = variantOptionsTableClientIdField;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for variantOptionsTableClientSecretField
|
||||
*******************************************************************************/
|
||||
public String getVariantOptionsTableClientSecretField()
|
||||
{
|
||||
return (this.variantOptionsTableClientSecretField);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for variantOptionsTableClientSecretField
|
||||
*******************************************************************************/
|
||||
public void setVariantOptionsTableClientSecretField(String variantOptionsTableClientSecretField)
|
||||
{
|
||||
this.variantOptionsTableClientSecretField = variantOptionsTableClientSecretField;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for variantOptionsTableClientSecretField
|
||||
*******************************************************************************/
|
||||
public QBackendMetaData withVariantOptionsTableClientSecretField(String variantOptionsTableClientSecretField)
|
||||
{
|
||||
this.variantOptionsTableClientSecretField = variantOptionsTableClientSecretField;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -39,6 +39,9 @@ public class ParentWidgetMetaData extends QWidgetMetaData
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public enum LayoutType
|
||||
{
|
||||
GRID,
|
||||
|
@ -188,7 +188,8 @@ public class FieldAdornment
|
||||
** Fluent setter for values
|
||||
**
|
||||
*******************************************************************************/
|
||||
public FieldAdornment withValues(Pair<String, Serializable>... values)
|
||||
@SafeVarargs
|
||||
public final FieldAdornment withValues(Pair<String, Serializable>... values)
|
||||
{
|
||||
for(Pair<String, Serializable> value : values)
|
||||
{
|
||||
|
@ -168,11 +168,11 @@ public class QFrontendTableMetaData
|
||||
editPermission = PermissionsHelper.hasTablePermission(actionInput, tableMetaData.getName(), TablePermissionSubType.EDIT);
|
||||
deletePermission = PermissionsHelper.hasTablePermission(actionInput, tableMetaData.getName(), TablePermissionSubType.DELETE);
|
||||
|
||||
QBackendMetaData backend = actionInput.getInstance().getBackend(tableMetaData.getBackendName());
|
||||
QBackendMetaData backend = QContext.getQInstance().getBackend(tableMetaData.getBackendName());
|
||||
if(backend != null && backend.getUsesVariants())
|
||||
{
|
||||
usesVariants = true;
|
||||
variantTableLabel = actionInput.getInstance().getTable(backend.getVariantOptionsTableName()).getLabel();
|
||||
variantTableLabel = QContext.getQInstance().getTable(backend.getVariantOptionsTableName()).getLabel();
|
||||
}
|
||||
|
||||
this.helpContents = tableMetaData.getHelpContent();
|
||||
|
@ -32,6 +32,13 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||
/*******************************************************************************
|
||||
** Meta-data definition of a source of data for a report (e.g., a table and query
|
||||
** filter or custom-code reference).
|
||||
**
|
||||
** Runs in 3 modes:
|
||||
**
|
||||
** - If a customRecordSource is specified, then that code is executed to get the records.
|
||||
** - else, if a sourceTable is specified, then the corresponding queryFilter
|
||||
** (optionally along with queryJoins and queryInputCustomizer) is used.
|
||||
** - else a staticDataSupplier is used.
|
||||
*******************************************************************************/
|
||||
public class QReportDataSource
|
||||
{
|
||||
@ -44,6 +51,7 @@ public class QReportDataSource
|
||||
|
||||
private QCodeReference queryInputCustomizer;
|
||||
private QCodeReference staticDataSupplier;
|
||||
private QCodeReference customRecordSource;
|
||||
|
||||
|
||||
|
||||
@ -265,4 +273,35 @@ public class QReportDataSource
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for customRecordSource
|
||||
*******************************************************************************/
|
||||
public QCodeReference getCustomRecordSource()
|
||||
{
|
||||
return (this.customRecordSource);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for customRecordSource
|
||||
*******************************************************************************/
|
||||
public void setCustomRecordSource(QCodeReference customRecordSource)
|
||||
{
|
||||
this.customRecordSource = customRecordSource;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for customRecordSource
|
||||
*******************************************************************************/
|
||||
public QReportDataSource withCustomRecordSource(QCodeReference customRecordSource)
|
||||
{
|
||||
this.customRecordSource = customRecordSource;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -804,7 +804,7 @@ public class QTableMetaData implements QAppChildMetaData, Serializable, MetaData
|
||||
{
|
||||
if(this.associatedScripts == null)
|
||||
{
|
||||
this.associatedScripts = new ArrayList();
|
||||
this.associatedScripts = new ArrayList<>();
|
||||
}
|
||||
this.associatedScripts.add(associatedScript);
|
||||
return (this);
|
||||
|
@ -32,6 +32,9 @@ import com.kingsrook.qqq.backend.core.model.metadata.tables.UniqueKey;
|
||||
*******************************************************************************/
|
||||
public class CacheUseCase
|
||||
{
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
public enum Type
|
||||
{
|
||||
PRIMARY_KEY_TO_PRIMARY_KEY, // e.g., the primary key in the cache table equals the primary key in the source table.
|
||||
|
@ -662,7 +662,11 @@ public class MemoryRecordStore
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
return ((Comparable) a).compareTo(b);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Comparable<Serializable> comparableSerializableA = (Comparable<Serializable>) a;
|
||||
|
||||
return comparableSerializableA.compareTo(b);
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -769,6 +773,7 @@ public class MemoryRecordStore
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private static Serializable computeAggregate(List<QRecord> records, Aggregate aggregate, QTableMetaData table)
|
||||
{
|
||||
String fieldName = aggregate.getFieldName();
|
||||
|
@ -27,6 +27,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessSummaryLine;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessSummaryLineInterface;
|
||||
@ -76,7 +77,7 @@ public class BulkDeleteLoadStep extends LoadViaDeleteStep implements ProcessSumm
|
||||
{
|
||||
super.preRun(runBackendStepInput, runBackendStepOutput);
|
||||
|
||||
QTableMetaData table = runBackendStepInput.getInstance().getTable(runBackendStepInput.getTableName());
|
||||
QTableMetaData table = QContext.getQInstance().getTable(runBackendStepInput.getTableName());
|
||||
if(table != null)
|
||||
{
|
||||
tableLabel = table.getLabel();
|
||||
@ -119,7 +120,7 @@ public class BulkDeleteLoadStep extends LoadViaDeleteStep implements ProcessSumm
|
||||
////////////////////////////
|
||||
super.runOnePage(runBackendStepInput, runBackendStepOutput);
|
||||
|
||||
QTableMetaData table = runBackendStepInput.getInstance().getTable(runBackendStepInput.getTableName());
|
||||
QTableMetaData table = QContext.getQInstance().getTable(runBackendStepInput.getTableName());
|
||||
String primaryKeyFieldName = table.getPrimaryKeyField();
|
||||
Map<Serializable, QRecord> outputRecordMap = runBackendStepOutput.getRecords().stream().collect(Collectors.toMap(r -> r.getValue(primaryKeyFieldName), r -> r, (a, b) -> a));
|
||||
|
||||
|
@ -27,6 +27,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessSummaryLine;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessSummaryLineInterface;
|
||||
@ -65,7 +66,7 @@ public class BulkDeleteTransformStep extends AbstractTransformStep
|
||||
///////////////////////////////////////////////////////
|
||||
// capture the table label - for the process summary //
|
||||
///////////////////////////////////////////////////////
|
||||
QTableMetaData table = runBackendStepInput.getInstance().getTable(runBackendStepInput.getTableName());
|
||||
QTableMetaData table = QContext.getQInstance().getTable(runBackendStepInput.getTableName());
|
||||
if(table != null)
|
||||
{
|
||||
tableLabel = table.getLabel();
|
||||
|
@ -25,6 +25,7 @@ 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.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessSummaryLine;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessSummaryLineInterface;
|
||||
@ -99,7 +100,7 @@ public class BulkEditLoadStep extends LoadViaUpdateStep implements ProcessSummar
|
||||
{
|
||||
super.preRun(runBackendStepInput, runBackendStepOutput);
|
||||
|
||||
QTableMetaData table = runBackendStepInput.getInstance().getTable(runBackendStepInput.getTableName());
|
||||
QTableMetaData table = QContext.getQInstance().getTable(runBackendStepInput.getTableName());
|
||||
if(table != null)
|
||||
{
|
||||
tableLabel = table.getLabel();
|
||||
@ -124,7 +125,7 @@ public class BulkEditLoadStep extends LoadViaUpdateStep implements ProcessSummar
|
||||
////////////////////////////////////////////////////////
|
||||
// roll up results based on output from update action //
|
||||
////////////////////////////////////////////////////////
|
||||
QTableMetaData table = runBackendStepInput.getInstance().getTable(runBackendStepInput.getTableName());
|
||||
QTableMetaData table = QContext.getQInstance().getTable(runBackendStepInput.getTableName());
|
||||
for(QRecord record : runBackendStepOutput.getRecords())
|
||||
{
|
||||
Serializable recordPrimaryKey = record.getValue(table.getPrimaryKeyField());
|
||||
|
@ -31,6 +31,7 @@ import java.util.Optional;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.values.QPossibleValueTranslator;
|
||||
import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessSummaryLine;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessSummaryLineInterface;
|
||||
@ -81,7 +82,7 @@ public class BulkEditTransformStep extends AbstractTransformStep
|
||||
///////////////////////////////////////////////////////
|
||||
// capture the table label - for the process summary //
|
||||
///////////////////////////////////////////////////////
|
||||
table = runBackendStepInput.getInstance().getTable(runBackendStepInput.getTableName());
|
||||
table = QContext.getQInstance().getTable(runBackendStepInput.getTableName());
|
||||
if(table != null)
|
||||
{
|
||||
tableLabel = table.getLabel();
|
||||
@ -230,7 +231,7 @@ public class BulkEditTransformStep extends AbstractTransformStep
|
||||
|
||||
if(field.getPossibleValueSourceName() != null)
|
||||
{
|
||||
QPossibleValueTranslator qPossibleValueTranslator = new QPossibleValueTranslator(runBackendStepInput.getInstance(), runBackendStepInput.getSession());
|
||||
QPossibleValueTranslator qPossibleValueTranslator = new QPossibleValueTranslator(QContext.getQInstance(), QContext.getQSession());
|
||||
String translatedValue = qPossibleValueTranslator.translatePossibleValue(field, value);
|
||||
if(StringUtils.hasContent(translatedValue))
|
||||
{
|
||||
|
@ -27,6 +27,7 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import com.kingsrook.qqq.backend.core.adapters.CsvToQRecordAdapter;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.QUploadedFile;
|
||||
@ -83,7 +84,7 @@ public class BulkInsertExtractStep extends AbstractExtractStep
|
||||
.withLimit(getLimit())
|
||||
.withCsv(new String(bytes))
|
||||
.withDoCorrectValueTypes(true)
|
||||
.withTable(runBackendStepInput.getInstance().getTable(tableName))
|
||||
.withTable(QContext.getQInstance().getTable(tableName))
|
||||
.withMapping(mapping)
|
||||
.withRecordCustomizer((record) ->
|
||||
{
|
||||
|
@ -38,6 +38,7 @@ import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizerInterfa
|
||||
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.helpers.UniqueKeyHelper;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessSummaryLine;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.ProcessSummaryLineInterface;
|
||||
@ -104,7 +105,7 @@ public class BulkInsertTransformStep extends AbstractTransformStep
|
||||
@Override
|
||||
public void preRun(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||
{
|
||||
this.table = runBackendStepInput.getInstance().getTable(runBackendStepInput.getTableName());
|
||||
this.table = QContext.getQInstance().getTable(runBackendStepInput.getTableName());
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// since we're doing a unique key check in this class, we can tell the loadViaInsert step that it (rather, the InsertAction) doesn't need to re-do one. //
|
||||
@ -121,7 +122,7 @@ public class BulkInsertTransformStep extends AbstractTransformStep
|
||||
public void runOnePage(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||
{
|
||||
int rowsInThisPage = runBackendStepInput.getRecords().size();
|
||||
QTableMetaData table = runBackendStepInput.getInstance().getTable(runBackendStepInput.getTableName());
|
||||
QTableMetaData table = QContext.getQInstance().getTable(runBackendStepInput.getTableName());
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// set up an insert-input, which will be used as input to the pre-customizer as well as for additional validations //
|
||||
|
@ -28,6 +28,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.adapters.JsonToQFieldMappingAdapter;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
@ -85,7 +86,7 @@ public class BasicETLTransformFunction implements BackendStep
|
||||
throw (new QException("Mapping was not a Key-based mapping type. Was a : " + mapping.getClass().getName()));
|
||||
}
|
||||
|
||||
QTableMetaData table = runBackendStepInput.getInstance().getTable(tableName);
|
||||
QTableMetaData table = QContext.getQInstance().getTable(tableName);
|
||||
List<QRecord> mappedRecords = applyMapping(runBackendStepInput.getRecords(), table, keyBasedFieldMapping);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -27,6 +27,7 @@ import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
|
||||
import com.kingsrook.qqq.backend.core.actions.values.QPossibleValueTranslator;
|
||||
import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
@ -85,14 +86,14 @@ public class BaseStreamedETLStep
|
||||
protected void updateRecordsWithDisplayValuesAndPossibleValues(RunBackendStepInput input, List<QRecord> list)
|
||||
{
|
||||
String destinationTable = input.getValueString(StreamedETLWithFrontendProcess.FIELD_DESTINATION_TABLE);
|
||||
QTableMetaData table = input.getInstance().getTable(destinationTable);
|
||||
QTableMetaData table = QContext.getQInstance().getTable(destinationTable);
|
||||
|
||||
if(table != null && list != null)
|
||||
{
|
||||
QValueFormatter qValueFormatter = new QValueFormatter();
|
||||
qValueFormatter.setDisplayValuesInRecords(table, list);
|
||||
|
||||
QPossibleValueTranslator qPossibleValueTranslator = new QPossibleValueTranslator(input.getInstance(), input.getSession());
|
||||
QPossibleValueTranslator qPossibleValueTranslator = new QPossibleValueTranslator(QContext.getQInstance(), QContext.getQSession());
|
||||
qPossibleValueTranslator.translatePossibleValuesInRecords(table, list);
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import com.kingsrook.qqq.backend.core.actions.reporting.DistinctFilteringRecordP
|
||||
import com.kingsrook.qqq.backend.core.actions.reporting.RecordPipe;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
@ -267,7 +268,7 @@ public class ExtractViaQueryStep extends AbstractExtractStep
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// else, check for recordIds from a frontend launching of a process //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
QTableMetaData table = runBackendStepInput.getInstance().getTable(runBackendStepInput.getValueString(FIELD_SOURCE_TABLE));
|
||||
QTableMetaData table = QContext.getQInstance().getTable(runBackendStepInput.getValueString(FIELD_SOURCE_TABLE));
|
||||
if(table == null)
|
||||
{
|
||||
throw (new QException("source table name was not set - could not load records by id"));
|
||||
@ -319,7 +320,7 @@ public class ExtractViaQueryStep extends AbstractExtractStep
|
||||
if(needDistinctPipe)
|
||||
{
|
||||
String sourceTableName = runBackendStepInput.getValueString(StreamedETLWithFrontendProcess.FIELD_SOURCE_TABLE);
|
||||
QTableMetaData sourceTable = runBackendStepInput.getInstance().getTable(sourceTableName);
|
||||
QTableMetaData sourceTable = QContext.getQInstance().getTable(sourceTableName);
|
||||
return (new DistinctFilteringRecordPipe(new UniqueKey(sourceTable.getPrimaryKeyField()), overrideCapacity));
|
||||
}
|
||||
else
|
||||
|
@ -28,6 +28,7 @@ import java.util.Optional;
|
||||
import com.kingsrook.qqq.backend.core.actions.QBackendTransaction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
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;
|
||||
@ -86,7 +87,7 @@ public class LoadViaInsertOrUpdateStep extends AbstractLoadStep
|
||||
*******************************************************************************/
|
||||
public void insertAndUpdateRecords(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||
{
|
||||
QTableMetaData tableMetaData = runBackendStepInput.getInstance().getTable(runBackendStepInput.getValueString(FIELD_DESTINATION_TABLE));
|
||||
QTableMetaData tableMetaData = QContext.getQInstance().getTable(runBackendStepInput.getValueString(FIELD_DESTINATION_TABLE));
|
||||
|
||||
if(CollectionUtils.nullSafeHasContents(recordsToInsert))
|
||||
{
|
||||
@ -139,7 +140,7 @@ public class LoadViaInsertOrUpdateStep extends AbstractLoadStep
|
||||
*******************************************************************************/
|
||||
protected void evaluateRecords(RunBackendStepInput runBackendStepInput) throws QException
|
||||
{
|
||||
QTableMetaData tableMetaData = runBackendStepInput.getInstance().getTable(runBackendStepInput.getValueString(FIELD_DESTINATION_TABLE));
|
||||
QTableMetaData tableMetaData = QContext.getQInstance().getTable(runBackendStepInput.getValueString(FIELD_DESTINATION_TABLE));
|
||||
recordsToInsert = new ArrayList<>();
|
||||
recordsToUpdate = new ArrayList<>();
|
||||
|
||||
|
@ -162,10 +162,10 @@ public class StreamedETLPreviewStep extends BaseStreamedETLStep implements Backe
|
||||
private void countRecords(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput, AbstractExtractStep extractStep) throws QException
|
||||
{
|
||||
String sourceTableName = runBackendStepInput.getValueString(StreamedETLWithFrontendProcess.FIELD_SOURCE_TABLE);
|
||||
QTableMetaData sourceTable = runBackendStepInput.getInstance().getTable(sourceTableName);
|
||||
QTableMetaData sourceTable = QContext.getQInstance().getTable(sourceTableName);
|
||||
if(StringUtils.hasContent(sourceTableName))
|
||||
{
|
||||
QBackendMetaData sourceTableBackend = runBackendStepInput.getInstance().getBackendForTable(sourceTableName);
|
||||
QBackendMetaData sourceTableBackend = QContext.getQInstance().getBackendForTable(sourceTableName);
|
||||
if(sourceTable.isCapabilityEnabled(sourceTableBackend, Capability.TABLE_COUNT))
|
||||
{
|
||||
Integer recordCount = extractStep.doCount(runBackendStepInput);
|
||||
|
@ -65,9 +65,14 @@ public class MergeDuplicatesLoadStep extends LoadViaInsertOrUpdateStep
|
||||
{
|
||||
super.runOnePage(runBackendStepInput, runBackendStepOutput);
|
||||
|
||||
ListingHash<String, Serializable> otherTableIdsToDelete = (ListingHash<String, Serializable>) runBackendStepInput.getValue("otherTableIdsToDelete");
|
||||
@SuppressWarnings("unchecked")
|
||||
ListingHash<String, Serializable> otherTableIdsToDelete = (ListingHash<String, Serializable>) runBackendStepInput.getValue("otherTableIdsToDelete");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ListingHash<String, QQueryFilter> otherTableFiltersToDelete = (ListingHash<String, QQueryFilter>) runBackendStepInput.getValue("otherTableFiltersToDelete");
|
||||
ListingHash<String, QRecord> otherTableRecordsToStore = (ListingHash<String, QRecord>) runBackendStepInput.getValue("otherTableRecordsToStore");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ListingHash<String, QRecord> otherTableRecordsToStore = (ListingHash<String, QRecord>) runBackendStepInput.getValue("otherTableRecordsToStore");
|
||||
|
||||
if(otherTableIdsToDelete != null)
|
||||
{
|
||||
|
@ -46,7 +46,8 @@ public class BasicRunReportProcess
|
||||
public static final String STEP_NAME_EXECUTE = "execute";
|
||||
public static final String STEP_NAME_ACCESS = "accessReport";
|
||||
|
||||
public static final String FIELD_REPORT_NAME = "reportName";
|
||||
public static final String FIELD_REPORT_NAME = "reportName";
|
||||
public static final String FIELD_REPORT_FORMAT = "reportFormat";
|
||||
|
||||
|
||||
|
||||
|
@ -31,7 +31,9 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.actions.reporting.GenerateReportAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||
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.reporting.ReportDestination;
|
||||
@ -49,6 +51,7 @@ import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||
public class ExecuteReportStep implements BackendStep
|
||||
{
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@ -57,9 +60,10 @@ public class ExecuteReportStep implements BackendStep
|
||||
{
|
||||
try
|
||||
{
|
||||
String reportName = runBackendStepInput.getValueString("reportName");
|
||||
QReportMetaData report = runBackendStepInput.getInstance().getReport(reportName);
|
||||
File tmpFile = File.createTempFile(reportName, ".xlsx", new File("/tmp/"));
|
||||
ReportFormat reportFormat = getReportFormat(runBackendStepInput);
|
||||
String reportName = runBackendStepInput.getValueString("reportName");
|
||||
QReportMetaData report = QContext.getQInstance().getReport(reportName);
|
||||
File tmpFile = File.createTempFile(reportName, "." + reportFormat.getExtension());
|
||||
|
||||
runBackendStepInput.getAsyncJobCallback().updateStatus("Generating Report");
|
||||
|
||||
@ -68,7 +72,7 @@ public class ExecuteReportStep implements BackendStep
|
||||
ReportInput reportInput = new ReportInput();
|
||||
reportInput.setReportName(reportName);
|
||||
reportInput.setReportDestination(new ReportDestination()
|
||||
.withReportFormat(ReportFormat.XLSX) // todo - variable
|
||||
.withReportFormat(reportFormat)
|
||||
.withReportOutputStream(reportOutputStream));
|
||||
|
||||
Map<String, Serializable> values = runBackendStepInput.getValues();
|
||||
@ -78,7 +82,7 @@ public class ExecuteReportStep implements BackendStep
|
||||
|
||||
String downloadFileBaseName = getDownloadFileBaseName(runBackendStepInput, report);
|
||||
|
||||
runBackendStepOutput.addValue("downloadFileName", downloadFileBaseName + ".xlsx");
|
||||
runBackendStepOutput.addValue("downloadFileName", downloadFileBaseName + "." + reportFormat.getExtension());
|
||||
runBackendStepOutput.addValue("serverFilePath", tmpFile.getCanonicalPath());
|
||||
}
|
||||
}
|
||||
@ -90,6 +94,22 @@ public class ExecuteReportStep implements BackendStep
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
**
|
||||
***************************************************************************/
|
||||
private ReportFormat getReportFormat(RunBackendStepInput runBackendStepInput) throws QUserFacingException
|
||||
{
|
||||
String reportFormatInput = runBackendStepInput.getValueString(BasicRunReportProcess.FIELD_REPORT_FORMAT);
|
||||
if(StringUtils.hasContent(reportFormatInput))
|
||||
{
|
||||
return (ReportFormat.fromString(reportFormatInput));
|
||||
}
|
||||
|
||||
return (ReportFormat.XLSX);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
@ -26,6 +26,7 @@ import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
@ -106,15 +107,16 @@ public class PrepareReportForRecordStep extends PrepareReportStep
|
||||
}
|
||||
|
||||
String reportName = runBackendStepInput.getValueString("reportName");
|
||||
QReportMetaData report = runBackendStepInput.getInstance().getReport(reportName);
|
||||
QReportMetaData report = QContext.getQInstance().getReport(reportName);
|
||||
// runBackendStepOutput.addValue("downloadFileBaseName", runBackendStepInput.getTable().getLabel() + " " + record.getRecordLabel());
|
||||
runBackendStepOutput.addValue("downloadFileBaseName", report.getLabel() + " - " + record.getRecordLabel());
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// if there are no more input fields, then remove the INPUT step from the process. //
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
inputFieldList = (ArrayList<QFieldMetaData>) runBackendStepOutput.getValue("inputFieldList");
|
||||
if(!CollectionUtils.nullSafeHasContents(inputFieldList))
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<QFieldMetaData> updatedInputFieldList = (ArrayList<QFieldMetaData>) runBackendStepOutput.getValue("inputFieldList");
|
||||
if(!CollectionUtils.nullSafeHasContents(updatedInputFieldList))
|
||||
{
|
||||
removeInputStepFromProcess(runBackendStepOutput);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ package com.kingsrook.qqq.backend.core.processes.implementations.reports;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
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;
|
||||
@ -56,7 +57,7 @@ public class PrepareReportStep implements BackendStep
|
||||
throw (new QException("Process value [reportName] was not given."));
|
||||
}
|
||||
|
||||
QReportMetaData report = runBackendStepInput.getInstance().getReport(reportName);
|
||||
QReportMetaData report = QContext.getQInstance().getReport(reportName);
|
||||
if(report == null)
|
||||
{
|
||||
throw (new QException("Process named [" + reportName + "] was not found in this instance."));
|
||||
|
@ -29,6 +29,7 @@ import com.kingsrook.qqq.backend.core.actions.processes.BackendStep;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepOutput;
|
||||
@ -44,6 +45,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.savedviews.SavedView;
|
||||
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -78,10 +80,10 @@ public class QuerySavedViewProcess implements BackendStep
|
||||
public void run(RunBackendStepInput runBackendStepInput, RunBackendStepOutput runBackendStepOutput) throws QException
|
||||
{
|
||||
ActionHelper.validateSession(runBackendStepInput);
|
||||
Integer savedViewId = runBackendStepInput.getValueInteger("id");
|
||||
|
||||
try
|
||||
{
|
||||
Integer savedViewId = runBackendStepInput.getValueInteger("id");
|
||||
if(savedViewId != null)
|
||||
{
|
||||
GetInput input = new GetInput();
|
||||
@ -89,6 +91,11 @@ public class QuerySavedViewProcess implements BackendStep
|
||||
input.setPrimaryKey(savedViewId);
|
||||
|
||||
GetOutput output = new GetAction().execute(input);
|
||||
if(output.getRecord() == null)
|
||||
{
|
||||
throw (new QNotFoundException("The requested view was not found."));
|
||||
}
|
||||
|
||||
runBackendStepOutput.addRecord(output.getRecord());
|
||||
runBackendStepOutput.addValue("savedView", output.getRecord());
|
||||
runBackendStepOutput.addValue("savedViewList", (Serializable) List.of(output.getRecord()));
|
||||
@ -108,6 +115,11 @@ public class QuerySavedViewProcess implements BackendStep
|
||||
runBackendStepOutput.addValue("savedViewList", (Serializable) output.getRecords());
|
||||
}
|
||||
}
|
||||
catch(QNotFoundException qnfe)
|
||||
{
|
||||
LOG.info("View not found", logPair("savedViewId", savedViewId));
|
||||
throw (qnfe);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
LOG.warn("Error querying for saved views", e);
|
||||
|
@ -145,7 +145,7 @@ public class StoreScriptRevisionProcessStep implements BackendStep
|
||||
|
||||
try
|
||||
{
|
||||
scriptRevision.setValue("author", input.getSession().getUser().getFullName());
|
||||
scriptRevision.setValue("author", QContext.getQSession().getUser().getFullName());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
@ -139,7 +139,7 @@ public class TestScriptProcessStep implements BackendStep
|
||||
//////////////////////////////////
|
||||
// send script outputs back out //
|
||||
//////////////////////////////////
|
||||
output.addValue("scriptLogLines", CollectionUtils.useOrWrap(testScriptOutput.getScriptLogLines(), TypeToken.get(ArrayList.class)));
|
||||
output.addValue("scriptLogLines", CollectionUtils.useOrWrap(testScriptOutput.getScriptLogLines(), new TypeToken<ArrayList<QRecord>>() {}));
|
||||
output.addValue("outputObject", testScriptOutput.getOutputObject());
|
||||
|
||||
if(testScriptOutput.getException() != null)
|
||||
|
@ -365,10 +365,10 @@ public abstract class AbstractTableSyncTransformStep extends AbstractTransformSt
|
||||
{
|
||||
if(possibleValueTranslator == null)
|
||||
{
|
||||
possibleValueTranslator = new QPossibleValueTranslator(runBackendStepInput.getInstance(), runBackendStepInput.getSession());
|
||||
possibleValueTranslator = new QPossibleValueTranslator(QContext.getQInstance(), QContext.getQSession());
|
||||
}
|
||||
|
||||
possibleValueTranslator.translatePossibleValuesInRecords(runBackendStepInput.getInstance().getTable(destinationTableName), runBackendStepOutput.getRecords());
|
||||
possibleValueTranslator.translatePossibleValuesInRecords(QContext.getQInstance().getTable(destinationTableName), runBackendStepOutput.getRecords());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -433,6 +433,8 @@ public class ProcessLockUtils
|
||||
{
|
||||
throw (new QException("Error deleting processLock record: " + deleteOutput.getRecordsWithErrors().get(0).getErrorsAsString()));
|
||||
}
|
||||
|
||||
LOG.info("Released process lock", logPair("id", processLock.getId()), logPair("key", processLock.getKey()), logPair("typeId", processLock.getProcessLockTypeId()), logPair("details", processLock.getDetails()));
|
||||
}
|
||||
catch(QException e)
|
||||
{
|
||||
|
@ -32,6 +32,7 @@ import java.util.function.Consumer;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
||||
@ -515,7 +516,7 @@ public class GeneralProcessUtils
|
||||
*******************************************************************************/
|
||||
public static Integer validateSingleSelectedId(RunBackendStepInput runBackendStepInput, String tableName) throws QException
|
||||
{
|
||||
String tableLabel = runBackendStepInput.getInstance().getTable(tableName).getLabel();
|
||||
String tableLabel = QContext.getQInstance().getTable(tableName).getLabel();
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Get the selected recordId and verify we only 1 //
|
||||
|
@ -70,7 +70,9 @@ public class QuartzJobRunner implements Job
|
||||
QContext.init(qInstance, quartzScheduler.getSessionSupplier().get());
|
||||
|
||||
schedulableType = qInstance.getSchedulableType(context.getJobDetail().getJobDataMap().getString("type"));
|
||||
params = (Map<String, Object>) context.getJobDetail().getJobDataMap().get("params");
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> paramsFromJobDataMap = (Map<String, Object>) context.getJobDetail().getJobDataMap().get("params");
|
||||
params = paramsFromJobDataMap;
|
||||
|
||||
SchedulableRunner schedulableRunner = QCodeLoader.getAdHoc(SchedulableRunner.class, schedulableType.getRunner());
|
||||
|
||||
|
@ -74,7 +74,9 @@ public class SchedulableProcessRunner implements SchedulableRunner
|
||||
Map<String, Serializable> backendVariantData = null;
|
||||
if(params.containsKey("backendVariantData"))
|
||||
{
|
||||
backendVariantData = (Map<String, Serializable>) params.get("backendVariantData");
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Serializable> dataFromMap = (Map<String, Serializable>) params.get("backendVariantData");
|
||||
backendVariantData = dataFromMap;
|
||||
}
|
||||
|
||||
Map<String, Serializable> processInputValues = buildProcessInputValuesMap(params, process);
|
||||
|
@ -26,6 +26,7 @@ import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
@ -78,7 +79,7 @@ public class TempFileStateProvider implements StateProviderInterface
|
||||
try
|
||||
{
|
||||
String json = JsonUtils.toJson(data);
|
||||
FileUtils.writeStringToFile(getFile(key), json);
|
||||
FileUtils.writeStringToFile(getFile(key), json, StandardCharsets.UTF_8);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
@ -97,7 +98,7 @@ public class TempFileStateProvider implements StateProviderInterface
|
||||
{
|
||||
try
|
||||
{
|
||||
String json = FileUtils.readFileToString(getFile(key));
|
||||
String json = FileUtils.readFileToString(getFile(key), StandardCharsets.UTF_8);
|
||||
return (Optional.of(JsonUtils.toObject(json, type)));
|
||||
}
|
||||
catch(FileNotFoundException | NoSuchFileException fnfe)
|
||||
|
@ -50,7 +50,7 @@ public class CollectionUtils
|
||||
** true if c is null or it's empty
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static boolean nullSafeIsEmpty(Collection c)
|
||||
public static boolean nullSafeIsEmpty(Collection<?> c)
|
||||
{
|
||||
if(c == null || c.isEmpty())
|
||||
{
|
||||
@ -66,7 +66,7 @@ public class CollectionUtils
|
||||
** true if c is null or it's empty
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static boolean nullSafeIsEmpty(Map c)
|
||||
public static boolean nullSafeIsEmpty(Map<?, ?> c)
|
||||
{
|
||||
if(c == null || c.isEmpty())
|
||||
{
|
||||
@ -82,7 +82,7 @@ public class CollectionUtils
|
||||
** true if c is NOT null and it's not empty
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static boolean nullSafeHasContents(Collection c)
|
||||
public static boolean nullSafeHasContents(Collection<?> c)
|
||||
{
|
||||
return (!nullSafeIsEmpty(c));
|
||||
}
|
||||
@ -93,7 +93,7 @@ public class CollectionUtils
|
||||
** true if c is NOT null and it's not empty
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static boolean nullSafeHasContents(Map c)
|
||||
public static boolean nullSafeHasContents(Map<?, ?> c)
|
||||
{
|
||||
return (!nullSafeIsEmpty(c));
|
||||
}
|
||||
@ -104,7 +104,7 @@ public class CollectionUtils
|
||||
** 0 if c is empty, otherwise, its size.
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static int nullSafeSize(Collection c)
|
||||
public static int nullSafeSize(Collection<?> c)
|
||||
{
|
||||
if(c == null)
|
||||
{
|
||||
@ -120,7 +120,7 @@ public class CollectionUtils
|
||||
** 0 if c is empty, otherwise, its size.
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static int nullSafeSize(Map c)
|
||||
public static int nullSafeSize(Map<?, ?> c)
|
||||
{
|
||||
if(c == null)
|
||||
{
|
||||
@ -302,14 +302,14 @@ public class CollectionUtils
|
||||
return (rs);
|
||||
}
|
||||
|
||||
List<T> currentPage = new LinkedList<T>();
|
||||
List<T> currentPage = new LinkedList<>();
|
||||
rs.add(currentPage);
|
||||
|
||||
for(T value : values)
|
||||
{
|
||||
if(currentPage.size() >= pageSize)
|
||||
{
|
||||
currentPage = new LinkedList<T>();
|
||||
currentPage = new LinkedList<>();
|
||||
rs.add(currentPage);
|
||||
}
|
||||
|
||||
@ -423,6 +423,7 @@ public class CollectionUtils
|
||||
**
|
||||
** Meant to help avoid null checks on foreach loops.
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[] nonNullArray(T[] array)
|
||||
{
|
||||
if(array == null)
|
||||
@ -539,7 +540,7 @@ public class CollectionUtils
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static Map objectToMap(Object o)
|
||||
public static Map<?, ?> objectToMap(Object o)
|
||||
{
|
||||
ObjectMapper mapper = new ObjectMapper()
|
||||
.registerModule(new JavaTimeModule())
|
||||
@ -555,6 +556,7 @@ public class CollectionUtils
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SafeVarargs
|
||||
public static <T> List<T> mergeLists(List<T>... lists)
|
||||
{
|
||||
List<T> rs = new ArrayList<>();
|
||||
@ -593,6 +595,7 @@ public class CollectionUtils
|
||||
return (null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> targetClass = (Class<T>) typeToken.getRawType();
|
||||
if(targetClass.isInstance(collection))
|
||||
{
|
||||
@ -630,6 +633,7 @@ public class CollectionUtils
|
||||
return (null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> targetClass = (Class<T>) typeToken.getRawType();
|
||||
if(targetClass.isInstance(collection))
|
||||
{
|
||||
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.utils;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import com.kingsrook.qqq.backend.core.utils.collections.MutableMap;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Hash that provides "counting" capability -- keys map to Integers that
|
||||
** are automatically/easily summed to
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class CountingHash<K extends Serializable> extends AbstractMap<K, Integer> implements Serializable
|
||||
{
|
||||
private Map<K, Integer> map = null;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Default constructor
|
||||
**
|
||||
*******************************************************************************/
|
||||
public CountingHash()
|
||||
{
|
||||
this.map = new HashMap<>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor where you can supply a source map (e.g., if you want a specific
|
||||
** Map type (like LinkedHashMap), or with pre-values.
|
||||
**
|
||||
** Note - the input map will be wrapped in a MutableMap - so - it'll be mutable.
|
||||
**
|
||||
*******************************************************************************/
|
||||
public CountingHash(Map<K, Integer> sourceMap)
|
||||
{
|
||||
this.map = new MutableMap<>(sourceMap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Increment the value for the specified key by 1.
|
||||
**
|
||||
*******************************************************************************/
|
||||
public Integer add(K key)
|
||||
{
|
||||
Integer value = getOrCreateListForKey(key);
|
||||
Integer sum = value + 1;
|
||||
map.put(key, sum);
|
||||
return (sum);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Increment the value for the specified key by the supplied addend
|
||||
**
|
||||
*******************************************************************************/
|
||||
public Integer add(K key, Integer addend)
|
||||
{
|
||||
Integer value = getOrCreateListForKey(key);
|
||||
Integer sum = value + addend;
|
||||
map.put(key, sum);
|
||||
return (sum);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private Integer getOrCreateListForKey(K key)
|
||||
{
|
||||
Integer value;
|
||||
|
||||
if(!this.map.containsKey(key))
|
||||
{
|
||||
this.map.put(key, 0);
|
||||
value = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = this.map.get(key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
***************************************************************************/
|
||||
public Set<Entry<K, Integer>> entrySet()
|
||||
{
|
||||
return this.map.entrySet();
|
||||
}
|
||||
|
||||
}
|
@ -37,6 +37,7 @@ public class ObjectUtils
|
||||
/*******************************************************************************
|
||||
** A varargs version of Objects.requireNonNullElse
|
||||
*******************************************************************************/
|
||||
@SafeVarargs
|
||||
public static <T> T requireNonNullElse(T... objects)
|
||||
{
|
||||
if(objects == null)
|
||||
|
@ -888,6 +888,7 @@ public class ValueUtils
|
||||
** Return the first argument that isn't null.
|
||||
** If all were null, return null.
|
||||
*******************************************************************************/
|
||||
@SafeVarargs
|
||||
public static <T> T getFirstNonNull(T... ts)
|
||||
{
|
||||
if(ts == null || ts.length == 0)
|
||||
|
@ -48,7 +48,11 @@ public class YamlUtils
|
||||
{
|
||||
ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
|
||||
objectMapper.findAndRegisterModules();
|
||||
return (objectMapper.readValue(yaml, Map.class));
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = objectMapper.readValue(yaml, Map.class);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,7 +86,7 @@ public class AlphaNumericComparator implements Comparator<String>
|
||||
////////////////////////////////////////////////////////////////
|
||||
if(INT_PATTERN.matcher(a).matches() && INT_PATTERN.matcher(b).matches())
|
||||
{
|
||||
int intsCompared = new Integer(a).compareTo(new Integer(b));
|
||||
int intsCompared = Integer.valueOf(a).compareTo(Integer.valueOf(b));
|
||||
if(intsCompared == TIE)
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -119,7 +119,7 @@ public class AlphaNumericComparator implements Comparator<String>
|
||||
/////////////////////////////////////////////////////////////
|
||||
// if the ints compare as non-zero, return that comparison //
|
||||
/////////////////////////////////////////////////////////////
|
||||
int intPartCompared = new Integer(aIntPart).compareTo(new Integer(bIntPart));
|
||||
int intPartCompared = Integer.valueOf(aIntPart).compareTo(Integer.valueOf(bIntPart));
|
||||
if(intPartCompared != TIE)
|
||||
{
|
||||
return (intPartCompared);
|
||||
|
@ -26,7 +26,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@SuppressWarnings({ "checkstyle:javadoc", "DanglingJavadoc" })
|
||||
/*******************************************************************************
|
||||
** List.of is "great", but annoying because it makes unmodifiable lists...
|
||||
** So, replace it with this, which returns ArrayLists, which "don't suck"
|
||||
|
@ -27,7 +27,6 @@ import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
||||
@SuppressWarnings({ "checkstyle:javadoc", "DanglingJavadoc" })
|
||||
/*******************************************************************************
|
||||
** Map.of is "great", but annoying because it makes unmodifiable maps, and it
|
||||
** NPE's on nulls... So, replace it with this, which returns HashMaps (or maps
|
||||
|
@ -87,7 +87,9 @@ public class MultiLevelMapHelper
|
||||
{
|
||||
try
|
||||
{
|
||||
return (map.getClass().getConstructor().newInstance());
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<K2, V> map1 = map.getClass().getConstructor().newInstance();
|
||||
return map1;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
@ -174,7 +174,7 @@ class StandardScheduledExecutorTest extends BaseTest
|
||||
@Override
|
||||
public void execute(RecordAutomationInput recordAutomationInput) throws QException
|
||||
{
|
||||
sessionId = recordAutomationInput.getSession().getIdReference();
|
||||
sessionId = QContext.getQSession().getIdReference();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ class ChildRecordListRendererTest extends BaseTest
|
||||
.getWidgetMetaData();
|
||||
qInstance.addWidget(widget);
|
||||
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
new QRecord().withValue("id", 1)
|
||||
));
|
||||
|
||||
@ -130,12 +130,12 @@ class ChildRecordListRendererTest extends BaseTest
|
||||
.getWidgetMetaData();
|
||||
qInstance.addWidget(widget);
|
||||
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
new QRecord().withValue("id", 1),
|
||||
new QRecord().withValue("id", 2)
|
||||
));
|
||||
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_LINE_ITEM), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_LINE_ITEM), List.of(
|
||||
new QRecord().withValue("orderId", 1).withValue("sku", "ABC").withValue("lineNumber", 2),
|
||||
new QRecord().withValue("orderId", 1).withValue("sku", "BCD").withValue("lineNumber", 1),
|
||||
new QRecord().withValue("orderId", 2).withValue("sku", "XYZ") // should not be found.
|
||||
|
@ -128,7 +128,7 @@ class ParentWidgetRendererTest extends BaseTest
|
||||
|
||||
QContext.getQSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_TYPE_STORE_ALL_ACCESS, true);
|
||||
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
new QRecord().withValue("id", 1)
|
||||
));
|
||||
|
||||
@ -161,12 +161,12 @@ class ParentWidgetRendererTest extends BaseTest
|
||||
|
||||
QContext.getQSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_TYPE_STORE_ALL_ACCESS, true);
|
||||
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
new QRecord().withValue("id", 1),
|
||||
new QRecord().withValue("id", 2)
|
||||
));
|
||||
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_LINE_ITEM), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_LINE_ITEM), List.of(
|
||||
new QRecord().withValue("orderId", 1).withValue("sku", "ABC").withValue("lineNumber", 2),
|
||||
new QRecord().withValue("orderId", 1).withValue("sku", "BCD").withValue("lineNumber", 1),
|
||||
new QRecord().withValue("orderId", 2).withValue("sku", "XYZ") // should not be found.
|
||||
|
@ -109,7 +109,7 @@ class ProcessWidgetRendererTest extends BaseTest
|
||||
.getWidgetMetaData();
|
||||
qInstance.addWidget(widget);
|
||||
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
new QRecord().withValue("id", 1)
|
||||
));
|
||||
|
||||
@ -140,12 +140,12 @@ class ProcessWidgetRendererTest extends BaseTest
|
||||
.getWidgetMetaData();
|
||||
qInstance.addWidget(widget);
|
||||
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
new QRecord().withValue("id", 1),
|
||||
new QRecord().withValue("id", 2)
|
||||
));
|
||||
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_LINE_ITEM), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_LINE_ITEM), List.of(
|
||||
new QRecord().withValue("orderId", 1).withValue("sku", "ABC").withValue("lineNumber", 2),
|
||||
new QRecord().withValue("orderId", 1).withValue("sku", "BCD").withValue("lineNumber", 1),
|
||||
new QRecord().withValue("orderId", 2).withValue("sku", "XYZ") // should not be found.
|
||||
|
@ -1,5 +1,22 @@
|
||||
/*
|
||||
* Copyright © 2022-2023. ColdTrack <contact@coldtrack.com>. All Rights Reserved.
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.actions.dashboard.widgets;
|
||||
|
@ -1,5 +1,22 @@
|
||||
/*
|
||||
* Copyright © 2022-2023. ColdTrack <contact@coldtrack.com>. All Rights Reserved.
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2024. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.core.actions.dashboard.widgets;
|
||||
|
@ -116,7 +116,7 @@ class USMapRendererTest extends BaseTest
|
||||
.getWidgetMetaData();
|
||||
qInstance.addWidget(widget);
|
||||
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
new QRecord().withValue("id", 1)
|
||||
));
|
||||
|
||||
@ -147,12 +147,12 @@ class USMapRendererTest extends BaseTest
|
||||
.getWidgetMetaData();
|
||||
qInstance.addWidget(widget);
|
||||
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
new QRecord().withValue("id", 1),
|
||||
new QRecord().withValue("id", 2)
|
||||
));
|
||||
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_LINE_ITEM), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_LINE_ITEM), List.of(
|
||||
new QRecord().withValue("orderId", 1).withValue("sku", "ABC").withValue("lineNumber", 2),
|
||||
new QRecord().withValue("orderId", 1).withValue("sku", "BCD").withValue("lineNumber", 1),
|
||||
new QRecord().withValue("orderId", 2).withValue("sku", "XYZ") // should not be found.
|
||||
|
@ -67,7 +67,8 @@ class ProcessMetaDataActionTest extends BaseTest
|
||||
@Test
|
||||
public void test_notFound()
|
||||
{
|
||||
assertThrows(QNotFoundException.class, () -> {
|
||||
assertThrows(QNotFoundException.class, () ->
|
||||
{
|
||||
ProcessMetaDataInput request = new ProcessMetaDataInput();
|
||||
request.setProcessName("willNotBeFound");
|
||||
new ProcessMetaDataAction().execute(request);
|
||||
|
@ -65,7 +65,8 @@ class TableMetaDataActionTest extends BaseTest
|
||||
@Test
|
||||
public void test_notFound()
|
||||
{
|
||||
assertThrows(QUserFacingException.class, () -> {
|
||||
assertThrows(QUserFacingException.class, () ->
|
||||
{
|
||||
TableMetaDataInput request = new TableMetaDataInput();
|
||||
request.setTableName("willNotBeFound");
|
||||
new TableMetaDataAction().execute(request);
|
||||
|
@ -51,16 +51,16 @@ public class RunProcessUpdateStepListTest extends BaseTest
|
||||
{
|
||||
private static final String PROCESS_NAME = RunProcessUpdateStepListTest.class.getSimpleName();
|
||||
|
||||
private final static String STEP_START = "start";
|
||||
private final static String STEP_A = "a";
|
||||
private final static String STEP_B = "b";
|
||||
private final static String STEP_C = "c";
|
||||
private final static String STEP_1 = "1";
|
||||
private final static String STEP_2 = "2";
|
||||
private final static String STEP_3 = "3";
|
||||
private final static String STEP_END = "end";
|
||||
private static final String STEP_START = "start";
|
||||
private static final String STEP_A = "a";
|
||||
private static final String STEP_B = "b";
|
||||
private static final String STEP_C = "c";
|
||||
private static final String STEP_1 = "1";
|
||||
private static final String STEP_2 = "2";
|
||||
private static final String STEP_3 = "3";
|
||||
private static final String STEP_END = "end";
|
||||
|
||||
private final static List<String> LETTERS_STEP_LIST = List.of(
|
||||
private static final List<String> LETTERS_STEP_LIST = List.of(
|
||||
STEP_START,
|
||||
STEP_A,
|
||||
STEP_B,
|
||||
@ -68,7 +68,7 @@ public class RunProcessUpdateStepListTest extends BaseTest
|
||||
STEP_END
|
||||
);
|
||||
|
||||
private final static List<String> NUMBERS_STEP_LIST = List.of(
|
||||
private static final List<String> NUMBERS_STEP_LIST = List.of(
|
||||
STEP_START,
|
||||
STEP_1,
|
||||
STEP_2,
|
||||
|
@ -155,12 +155,12 @@ class ExportActionTest extends BaseTest
|
||||
QInstance qInstance = QContext.getQInstance();
|
||||
QContext.getQSession().withSecurityKeyValue(TestUtils.SECURITY_KEY_TYPE_STORE_ALL_ACCESS, true);
|
||||
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_ORDER), List.of(
|
||||
new QRecord().withValue("id", 1).withValue("orderNo", "ORD1").withValue("storeId", 1),
|
||||
new QRecord().withValue("id", 2).withValue("orderNo", "ORD2").withValue("storeId", 1)
|
||||
));
|
||||
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_LINE_ITEM), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_LINE_ITEM), List.of(
|
||||
new QRecord().withValue("id", 1).withValue("orderId", 1).withValue("sku", "A").withValue("quantity", 10),
|
||||
new QRecord().withValue("id", 2).withValue("orderId", 1).withValue("sku", "B").withValue("quantity", 15),
|
||||
new QRecord().withValue("id", 3).withValue("orderId", 2).withValue("sku", "A").withValue("quantity", 20)
|
||||
|
@ -562,7 +562,7 @@ public class GenerateReportActionTest extends BaseTest
|
||||
*******************************************************************************/
|
||||
public static void insertPersonRecords(QInstance qInstance) throws QException
|
||||
{
|
||||
TestUtils.insertRecords(qInstance, qInstance.getTable(TestUtils.TABLE_NAME_PERSON_MEMORY), List.of(
|
||||
TestUtils.insertRecords(qInstance.getTable(TestUtils.TABLE_NAME_PERSON_MEMORY), List.of(
|
||||
new PersonQRecord().withFirstName("Darin").withLastName("Jonson").withBirthDate(LocalDate.of(1980, Month.JANUARY, 31)).withNoOfShoes(null).withHomeStateId(1).withPrice(null).withCost(new BigDecimal("0.50")), // wrong last initial
|
||||
new PersonQRecord().withFirstName("Darin").withLastName("Jones").withBirthDate(LocalDate.of(1980, Month.JANUARY, 31)).withNoOfShoes(3).withHomeStateId(1).withPrice(new BigDecimal("1.00")).withCost(new BigDecimal("0.50")), // wrong last initial
|
||||
new PersonQRecord().withFirstName("Darin").withLastName("Kelly").withBirthDate(LocalDate.of(1979, Month.DECEMBER, 30)).withNoOfShoes(4).withHomeStateId(1).withPrice(new BigDecimal("1.20")).withCost(new BigDecimal("0.50")), // bad birthdate
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user