mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
Adding apps; starting field displayFormats
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -31,3 +31,4 @@ target/
|
|||||||
hs_err_pid*
|
hs_err_pid*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*.swp
|
*.swp
|
||||||
|
.flattened-pom.xml
|
||||||
|
@ -22,14 +22,19 @@
|
|||||||
package com.kingsrook.qqq.backend.core.actions.metadata;
|
package com.kingsrook.qqq.backend.core.actions.metadata;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
import com.kingsrook.qqq.backend.core.actions.ActionHelper;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput;
|
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendAppMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendProcessMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendProcessMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendTableMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppChildMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
|
|
||||||
@ -50,22 +55,87 @@ public class MetaDataAction
|
|||||||
// todo pre-customization - just get to modify the request?
|
// todo pre-customization - just get to modify the request?
|
||||||
MetaDataOutput metaDataOutput = new MetaDataOutput();
|
MetaDataOutput metaDataOutput = new MetaDataOutput();
|
||||||
|
|
||||||
|
Map<String, QFrontendAppMetaData> treeNodes = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
/////////////////////////////////////
|
||||||
|
// map tables to frontend metadata //
|
||||||
|
/////////////////////////////////////
|
||||||
Map<String, QFrontendTableMetaData> tables = new LinkedHashMap<>();
|
Map<String, QFrontendTableMetaData> tables = new LinkedHashMap<>();
|
||||||
for(Map.Entry<String, QTableMetaData> entry : metaDataInput.getInstance().getTables().entrySet())
|
for(Map.Entry<String, QTableMetaData> entry : metaDataInput.getInstance().getTables().entrySet())
|
||||||
{
|
{
|
||||||
tables.put(entry.getKey(), new QFrontendTableMetaData(entry.getValue(), false));
|
tables.put(entry.getKey(), new QFrontendTableMetaData(entry.getValue(), false));
|
||||||
|
treeNodes.put(entry.getKey(), new QFrontendAppMetaData(entry.getValue()));
|
||||||
}
|
}
|
||||||
metaDataOutput.setTables(tables);
|
metaDataOutput.setTables(tables);
|
||||||
|
|
||||||
|
////////////////////////////////////////
|
||||||
|
// map processes to frontend metadata //
|
||||||
|
////////////////////////////////////////
|
||||||
Map<String, QFrontendProcessMetaData> processes = new LinkedHashMap<>();
|
Map<String, QFrontendProcessMetaData> processes = new LinkedHashMap<>();
|
||||||
for(Map.Entry<String, QProcessMetaData> entry : metaDataInput.getInstance().getProcesses().entrySet())
|
for(Map.Entry<String, QProcessMetaData> entry : metaDataInput.getInstance().getProcesses().entrySet())
|
||||||
{
|
{
|
||||||
processes.put(entry.getKey(), new QFrontendProcessMetaData(entry.getValue(), false));
|
processes.put(entry.getKey(), new QFrontendProcessMetaData(entry.getValue(), false));
|
||||||
|
treeNodes.put(entry.getKey(), new QFrontendAppMetaData(entry.getValue()));
|
||||||
}
|
}
|
||||||
metaDataOutput.setProcesses(processes);
|
metaDataOutput.setProcesses(processes);
|
||||||
|
|
||||||
// todo post-customization - can do whatever w/ the result if you want
|
///////////////////////////////////
|
||||||
|
// map apps to frontend metadata //
|
||||||
|
///////////////////////////////////
|
||||||
|
Map<String, QFrontendAppMetaData> apps = new LinkedHashMap<>();
|
||||||
|
for(Map.Entry<String, QAppMetaData> entry : metaDataInput.getInstance().getApps().entrySet())
|
||||||
|
{
|
||||||
|
apps.put(entry.getKey(), new QFrontendAppMetaData(entry.getValue()));
|
||||||
|
treeNodes.put(entry.getKey(), new QFrontendAppMetaData(entry.getValue()));
|
||||||
|
|
||||||
|
for(QAppChildMetaData child : entry.getValue().getChildren())
|
||||||
|
{
|
||||||
|
apps.get(entry.getKey()).addChild(new QFrontendAppMetaData(child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metaDataOutput.setApps(apps);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
// organize app tree nodes by their hierarchy //
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
List<QFrontendAppMetaData> appTree = new ArrayList<>();
|
||||||
|
for(QAppMetaData appMetaData : metaDataInput.getInstance().getApps().values())
|
||||||
|
{
|
||||||
|
if(appMetaData.getParentAppName() == null)
|
||||||
|
{
|
||||||
|
buildAppTree(treeNodes, appTree, appMetaData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metaDataOutput.setAppTree(appTree);
|
||||||
|
|
||||||
|
// todo post-customization - can do whatever w/ the result if you want?
|
||||||
|
|
||||||
return metaDataOutput;
|
return metaDataOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void buildAppTree(Map<String, QFrontendAppMetaData> treeNodes, List<QFrontendAppMetaData> nodeList, QAppChildMetaData childMetaData)
|
||||||
|
{
|
||||||
|
QFrontendAppMetaData treeNode = treeNodes.get(childMetaData.getName());
|
||||||
|
if(treeNode == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeList.add(treeNode);
|
||||||
|
if(childMetaData instanceof QAppMetaData app)
|
||||||
|
{
|
||||||
|
if(app.getChildren() != null)
|
||||||
|
{
|
||||||
|
for(QAppChildMetaData child : app.getChildren())
|
||||||
|
{
|
||||||
|
buildAppTree(treeNodes, treeNode.getChildren(), child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.actions.values;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Utility to apply display formats to values for fields
|
||||||
|
*******************************************************************************/
|
||||||
|
public class QValueFormatter
|
||||||
|
{
|
||||||
|
private static final Logger LOG = LogManager.getLogger(QValueFormatter.class);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public static String formatValue(QFieldMetaData field, Serializable value)
|
||||||
|
{
|
||||||
|
//////////////////////////////////
|
||||||
|
// null values get null results //
|
||||||
|
//////////////////////////////////
|
||||||
|
if(value == null)
|
||||||
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
// if the field has a display format, try to apply it //
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
if(StringUtils.hasContent(field.getDisplayFormat()))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return (field.getDisplayFormat().formatted(value));
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
LOG.warn("Error formatting value [" + value + "] for field [" + field.getName() + "] with format [" + field.getDisplayFormat() + "]: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////
|
||||||
|
// by default, just get back a string //
|
||||||
|
////////////////////////////////////////
|
||||||
|
return (ValueUtils.getValueAsString(value));
|
||||||
|
}
|
||||||
|
}
|
@ -31,6 +31,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
|||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QComponentType;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QComponentType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendComponentMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendComponentMetaData;
|
||||||
@ -77,6 +78,11 @@ public class QInstanceEnricher
|
|||||||
{
|
{
|
||||||
qInstance.getBackends().values().forEach(this::enrich);
|
qInstance.getBackends().values().forEach(this::enrich);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(qInstance.getApps() != null)
|
||||||
|
{
|
||||||
|
qInstance.getApps().values().forEach(this::enrich);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -172,6 +178,19 @@ public class QInstanceEnricher
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void enrich(QAppMetaData app)
|
||||||
|
{
|
||||||
|
if(!StringUtils.hasContent(app.getLabel()))
|
||||||
|
{
|
||||||
|
app.setLabel(nameToLabel(app.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -23,10 +23,15 @@ package com.kingsrook.qqq.backend.core.instances;
|
|||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppChildMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
|
|
||||||
@ -76,60 +81,10 @@ public class QInstanceValidator
|
|||||||
List<String> errors = new ArrayList<>();
|
List<String> errors = new ArrayList<>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(assertCondition(errors, CollectionUtils.nullSafeHasContents(qInstance.getBackends()),
|
validateBackends(qInstance, errors);
|
||||||
"At least 1 backend must be defined."))
|
validateTables(qInstance, errors);
|
||||||
{
|
validateProcesses(qInstance, errors);
|
||||||
qInstance.getBackends().forEach((backendName, backend) ->
|
validateApps(qInstance, errors);
|
||||||
{
|
|
||||||
assertCondition(errors, Objects.equals(backendName, backend.getName()),
|
|
||||||
"Inconsistent naming for backend: " + backendName + "/" + backend.getName() + ".");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////
|
|
||||||
// validate the tables //
|
|
||||||
/////////////////////////
|
|
||||||
if(assertCondition(errors, CollectionUtils.nullSafeHasContents(qInstance.getTables()),
|
|
||||||
"At least 1 table must be defined."))
|
|
||||||
{
|
|
||||||
qInstance.getTables().forEach((tableName, table) ->
|
|
||||||
{
|
|
||||||
assertCondition(errors, Objects.equals(tableName, table.getName()),
|
|
||||||
"Inconsistent naming for table: " + tableName + "/" + table.getName() + ".");
|
|
||||||
|
|
||||||
////////////////////////////////////////
|
|
||||||
// validate the backend for the table //
|
|
||||||
////////////////////////////////////////
|
|
||||||
if(assertCondition(errors, StringUtils.hasContent(table.getBackendName()),
|
|
||||||
"Missing backend name for table " + tableName + "."))
|
|
||||||
{
|
|
||||||
if(CollectionUtils.nullSafeHasContents(qInstance.getBackends()))
|
|
||||||
{
|
|
||||||
assertCondition(errors, qInstance.getBackendForTable(tableName) != null,
|
|
||||||
"Unrecognized backend " + table.getBackendName() + " for table " + tableName + ".");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////
|
|
||||||
// validate fields in the table //
|
|
||||||
//////////////////////////////////
|
|
||||||
if(assertCondition(errors, CollectionUtils.nullSafeHasContents(table.getFields()),
|
|
||||||
"At least 1 field must be defined in table " + tableName + "."))
|
|
||||||
{
|
|
||||||
table.getFields().forEach((fieldName, field) ->
|
|
||||||
{
|
|
||||||
assertCondition(errors, Objects.equals(fieldName, field.getName()),
|
|
||||||
"Inconsistent naming in table " + tableName + " for field " + fieldName + "/" + field.getName() + ".");
|
|
||||||
|
|
||||||
if(field.getPossibleValueSourceName() != null)
|
|
||||||
{
|
|
||||||
assertCondition(errors, qInstance.getPossibleValueSource(field.getPossibleValueSourceName()) != null,
|
|
||||||
"Unrecognized possibleValueSourceName " + field.getPossibleValueSourceName() + " in table " + tableName + " for field " + fieldName + ".");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
@ -149,6 +104,181 @@ public class QInstanceValidator
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
private void validateBackends(QInstance qInstance, List<String> errors)
|
||||||
|
{
|
||||||
|
if(assertCondition(errors, CollectionUtils.nullSafeHasContents(qInstance.getBackends()), "At least 1 backend must be defined."))
|
||||||
|
{
|
||||||
|
qInstance.getBackends().forEach((backendName, backend) ->
|
||||||
|
{
|
||||||
|
assertCondition(errors, Objects.equals(backendName, backend.getName()), "Inconsistent naming for backend: " + backendName + "/" + backend.getName() + ".");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void validateTables(QInstance qInstance, List<String> errors)
|
||||||
|
{
|
||||||
|
if(assertCondition(errors, CollectionUtils.nullSafeHasContents(qInstance.getTables()),
|
||||||
|
"At least 1 table must be defined."))
|
||||||
|
{
|
||||||
|
qInstance.getTables().forEach((tableName, table) ->
|
||||||
|
{
|
||||||
|
assertCondition(errors, Objects.equals(tableName, table.getName()), "Inconsistent naming for table: " + tableName + "/" + table.getName() + ".");
|
||||||
|
|
||||||
|
validateAppChildHasValidParentAppName(qInstance, errors, table);
|
||||||
|
|
||||||
|
////////////////////////////////////////
|
||||||
|
// validate the backend for the table //
|
||||||
|
////////////////////////////////////////
|
||||||
|
if(assertCondition(errors, StringUtils.hasContent(table.getBackendName()),
|
||||||
|
"Missing backend name for table " + tableName + "."))
|
||||||
|
{
|
||||||
|
if(CollectionUtils.nullSafeHasContents(qInstance.getBackends()))
|
||||||
|
{
|
||||||
|
assertCondition(errors, qInstance.getBackendForTable(tableName) != null, "Unrecognized backend " + table.getBackendName() + " for table " + tableName + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////
|
||||||
|
// validate fields in the table //
|
||||||
|
//////////////////////////////////
|
||||||
|
if(assertCondition(errors, CollectionUtils.nullSafeHasContents(table.getFields()), "At least 1 field must be defined in table " + tableName + "."))
|
||||||
|
{
|
||||||
|
table.getFields().forEach((fieldName, field) ->
|
||||||
|
{
|
||||||
|
assertCondition(errors, Objects.equals(fieldName, field.getName()),
|
||||||
|
"Inconsistent naming in table " + tableName + " for field " + fieldName + "/" + field.getName() + ".");
|
||||||
|
|
||||||
|
if(field.getPossibleValueSourceName() != null)
|
||||||
|
{
|
||||||
|
assertCondition(errors, qInstance.getPossibleValueSource(field.getPossibleValueSourceName()) != null,
|
||||||
|
"Unrecognized possibleValueSourceName " + field.getPossibleValueSourceName() + " in table " + tableName + " for field " + fieldName + ".");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void validateProcesses(QInstance qInstance, List<String> errors)
|
||||||
|
{
|
||||||
|
if(!CollectionUtils.nullSafeIsEmpty(qInstance.getProcesses()))
|
||||||
|
{
|
||||||
|
qInstance.getProcesses().forEach((processName, process) ->
|
||||||
|
{
|
||||||
|
assertCondition(errors, Objects.equals(processName, process.getName()), "Inconsistent naming for process: " + processName + "/" + process.getName() + ".");
|
||||||
|
|
||||||
|
validateAppChildHasValidParentAppName(qInstance, errors, process);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////
|
||||||
|
// validate the table name for the process //
|
||||||
|
/////////////////////////////////////////////
|
||||||
|
if(process.getTableName() != null)
|
||||||
|
{
|
||||||
|
assertCondition(errors, qInstance.getTable(process.getTableName()) != null, "Unrecognized table " + process.getTableName() + " for process " + processName + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////
|
||||||
|
// validate steps in the process //
|
||||||
|
///////////////////////////////////
|
||||||
|
if(assertCondition(errors, CollectionUtils.nullSafeHasContents(process.getStepList()), "At least 1 step must be defined in process " + processName + "."))
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
for(QStepMetaData step : process.getStepList())
|
||||||
|
{
|
||||||
|
assertCondition(errors, StringUtils.hasContent(step.getName()), "Missing name for a step at index " + index + " in process " + processName);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void validateApps(QInstance qInstance, List<String> errors)
|
||||||
|
{
|
||||||
|
if(!CollectionUtils.nullSafeIsEmpty(qInstance.getApps()))
|
||||||
|
{
|
||||||
|
qInstance.getApps().forEach((appName, app) ->
|
||||||
|
{
|
||||||
|
assertCondition(errors, Objects.equals(appName, app.getName()), "Inconsistent naming for app: " + appName + "/" + app.getName() + ".");
|
||||||
|
|
||||||
|
validateAppChildHasValidParentAppName(qInstance, errors, app);
|
||||||
|
|
||||||
|
Set<String> appsVisited = new HashSet<>();
|
||||||
|
visitAppCheckingForCycles(app, appsVisited, errors);
|
||||||
|
|
||||||
|
if(app.getChildren() != null)
|
||||||
|
{
|
||||||
|
Set<String> childNames = new HashSet<>();
|
||||||
|
for(QAppChildMetaData child : app.getChildren())
|
||||||
|
{
|
||||||
|
assertCondition(errors, Objects.equals(appName, child.getParentAppName()), "Child " + child.getName() + " of app " + appName + " does not have its parent app properly set.");
|
||||||
|
assertCondition(errors, !childNames.contains(child.getName()), "App " + appName + " contains more than one child named " + child.getName());
|
||||||
|
childNames.add(child.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Check if an app's child list can recursively be traversed without finding a
|
||||||
|
** duplicate, which would indicate a cycle (e.g., an error)
|
||||||
|
*******************************************************************************/
|
||||||
|
private void visitAppCheckingForCycles(QAppMetaData app, Set<String> appsVisited, List<String> errors)
|
||||||
|
{
|
||||||
|
if(assertCondition(errors, !appsVisited.contains(app.getName()), "Circular app reference detected, involving " + app.getName()))
|
||||||
|
{
|
||||||
|
appsVisited.add(app.getName());
|
||||||
|
if(app.getChildren() != null)
|
||||||
|
{
|
||||||
|
for(QAppChildMetaData child : app.getChildren())
|
||||||
|
{
|
||||||
|
if(child instanceof QAppMetaData childApp)
|
||||||
|
{
|
||||||
|
visitAppCheckingForCycles(childApp, appsVisited, errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private void validateAppChildHasValidParentAppName(QInstance qInstance, List<String> errors, QAppChildMetaData appChild)
|
||||||
|
{
|
||||||
|
if(appChild.getParentAppName() != null)
|
||||||
|
{
|
||||||
|
assertCondition(errors, qInstance.getApp(appChild.getParentAppName()) != null, "Unrecognized parent app " + appChild.getParentAppName() + " for " + appChild.getName() + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** For the given input condition, if it's true, then we're all good (and return true).
|
||||||
|
** But if it's false, add the provided message to the list of errors (and return false,
|
||||||
|
** e.g., in case you need to stop evaluating rules to avoid exceptions).
|
||||||
|
*******************************************************************************/
|
||||||
private boolean assertCondition(List<String> errors, boolean condition, String message)
|
private boolean assertCondition(List<String> errors, boolean condition, String message)
|
||||||
{
|
{
|
||||||
if(!condition)
|
if(!condition)
|
||||||
|
@ -87,7 +87,7 @@ public abstract class AbstractActionInput
|
|||||||
catch(QInstanceValidationException e)
|
catch(QInstanceValidationException e)
|
||||||
{
|
{
|
||||||
LOG.warn(e);
|
LOG.warn(e);
|
||||||
throw (new IllegalArgumentException("QInstance failed validation" + e.getMessage()));
|
throw (new IllegalArgumentException("QInstance failed validation" + e.getMessage(), e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,10 @@
|
|||||||
package com.kingsrook.qqq.backend.core.model.actions.metadata;
|
package com.kingsrook.qqq.backend.core.model.actions.metadata;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendAppMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendProcessMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendProcessMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendTableMetaData;
|
||||||
|
|
||||||
@ -36,6 +38,9 @@ public class MetaDataOutput extends AbstractActionOutput
|
|||||||
{
|
{
|
||||||
private Map<String, QFrontendTableMetaData> tables;
|
private Map<String, QFrontendTableMetaData> tables;
|
||||||
private Map<String, QFrontendProcessMetaData> processes;
|
private Map<String, QFrontendProcessMetaData> processes;
|
||||||
|
private Map<String, QFrontendAppMetaData> apps;
|
||||||
|
|
||||||
|
private List<QFrontendAppMetaData> appTree;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -80,4 +85,49 @@ public class MetaDataOutput extends AbstractActionOutput
|
|||||||
{
|
{
|
||||||
this.processes = processes;
|
this.processes = processes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for appTree
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public List<QFrontendAppMetaData> getAppTree()
|
||||||
|
{
|
||||||
|
return appTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for appTree
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setAppTree(List<QFrontendAppMetaData> appTree)
|
||||||
|
{
|
||||||
|
this.appTree = appTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for apps
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Map<String, QFrontendAppMetaData> getApps()
|
||||||
|
{
|
||||||
|
return apps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for apps
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setApps(Map<String, QFrontendAppMetaData> apps)
|
||||||
|
{
|
||||||
|
this.apps = apps;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,9 @@ import java.util.ArrayList;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.values.QValueFormatter;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||||
|
|
||||||
@ -69,6 +71,7 @@ public class QRecord implements Serializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -105,6 +108,16 @@ public class QRecord implements Serializable
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setValue(QFieldMetaData field, Serializable value)
|
||||||
|
{
|
||||||
|
values.put(field.getName(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -126,6 +139,16 @@ public class QRecord implements Serializable
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setDisplayValue(QFieldMetaData field, Serializable rawValue)
|
||||||
|
{
|
||||||
|
displayValues.put(field.getName(), QValueFormatter.formatValue(field, rawValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -137,6 +160,17 @@ public class QRecord implements Serializable
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QRecord withDisplayValue(QFieldMetaData field, Serializable rawValue)
|
||||||
|
{
|
||||||
|
setDisplayValue(field, rawValue);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for tableName
|
** Getter for tableName
|
||||||
**
|
**
|
||||||
@ -355,6 +389,7 @@ public class QRecord implements Serializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for errors
|
** Getter for errors
|
||||||
**
|
**
|
||||||
@ -399,6 +434,7 @@ public class QRecord implements Serializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Convert this record to an QRecordEntity
|
** Convert this record to an QRecordEntity
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -24,10 +24,12 @@ package com.kingsrook.qqq.backend.core.model.metadata;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.kingsrook.qqq.backend.core.instances.QInstanceValidationKey;
|
import com.kingsrook.qqq.backend.core.instances.QInstanceValidationKey;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QStepMetaData;
|
||||||
@ -49,9 +51,13 @@ public class QInstance
|
|||||||
|
|
||||||
private QAuthenticationMetaData authentication = null;
|
private QAuthenticationMetaData authentication = null;
|
||||||
|
|
||||||
private Map<String, QTableMetaData> tables = new HashMap<>();
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
private Map<String, QPossibleValueSource<?>> possibleValueSources = new HashMap<>();
|
// Important to use LinkedHashmap here, to preserve the order in which entries are added. //
|
||||||
private Map<String, QProcessMetaData> processes = new HashMap<>();
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
private Map<String, QTableMetaData> tables = new LinkedHashMap<>();
|
||||||
|
private Map<String, QPossibleValueSource<?>> possibleValueSources = new LinkedHashMap<>();
|
||||||
|
private Map<String, QProcessMetaData> processes = new LinkedHashMap<>();
|
||||||
|
private Map<String, QAppMetaData> apps = new LinkedHashMap<>();
|
||||||
|
|
||||||
// todo - lock down the object (no more changes allowed) after it's been validated?
|
// todo - lock down the object (no more changes allowed) after it's been validated?
|
||||||
|
|
||||||
@ -171,6 +177,11 @@ public class QInstance
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public QTableMetaData getTable(String name)
|
public QTableMetaData getTable(String name)
|
||||||
{
|
{
|
||||||
|
if(this.tables == null)
|
||||||
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
return (this.tables.get(name));
|
return (this.tables.get(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,6 +271,40 @@ public class QInstance
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void addApp(QAppMetaData app)
|
||||||
|
{
|
||||||
|
this.addApp(app.getName(), app);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void addApp(String name, QAppMetaData app)
|
||||||
|
{
|
||||||
|
if(this.apps.containsKey(name))
|
||||||
|
{
|
||||||
|
throw (new IllegalArgumentException("Attempted to add a second app with name: " + name));
|
||||||
|
}
|
||||||
|
this.apps.put(name, app);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QAppMetaData getApp(String name)
|
||||||
|
{
|
||||||
|
return (this.apps.get(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for backends
|
** Getter for backends
|
||||||
**
|
**
|
||||||
@ -348,6 +393,28 @@ public class QInstance
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for apps
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Map<String, QAppMetaData> getApps()
|
||||||
|
{
|
||||||
|
return apps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for apps
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setApps(Map<String, QAppMetaData> apps)
|
||||||
|
{
|
||||||
|
this.apps = apps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for hasBeenValidated
|
** Getter for hasBeenValidated
|
||||||
**
|
**
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.metadata.fields;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public interface DisplayFormat
|
||||||
|
{
|
||||||
|
String DEFAULT = "%s";
|
||||||
|
String STRING = "%s";
|
||||||
|
String COMMAS = "%,d";
|
||||||
|
String DECIMAL1_COMMAS = "%,.1f";
|
||||||
|
String DECIMAL2_COMMAS = "%,.2f";
|
||||||
|
String DECIMAL3_COMMAS = "%,.3f";
|
||||||
|
String DECIMAL1 = "%.1f";
|
||||||
|
String DECIMAL2 = "%.2f";
|
||||||
|
String DECIMAL3 = "%.3f";
|
||||||
|
String CURRENCY = "$%,.2f";
|
||||||
|
}
|
@ -47,6 +47,7 @@ public class QFieldMetaData
|
|||||||
// propose doing that in a secondary field, e.g., "onlyEditableOn=insert|update" //
|
// propose doing that in a secondary field, e.g., "onlyEditableOn=insert|update" //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private String displayFormat = "%s";
|
||||||
private Serializable defaultValue;
|
private Serializable defaultValue;
|
||||||
private String possibleValueSourceName;
|
private String possibleValueSourceName;
|
||||||
|
|
||||||
@ -354,4 +355,36 @@ public class QFieldMetaData
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for displayFormat
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getDisplayFormat()
|
||||||
|
{
|
||||||
|
return displayFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for displayFormat
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setDisplayFormat(String displayFormat)
|
||||||
|
{
|
||||||
|
this.displayFormat = displayFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for displayFormat
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QFieldMetaData withDisplayFormat(String displayFormat)
|
||||||
|
{
|
||||||
|
this.displayFormat = displayFormat;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,10 @@ public enum QFieldType
|
|||||||
{
|
{
|
||||||
return (INTEGER);
|
return (INTEGER);
|
||||||
}
|
}
|
||||||
|
if(c.equals(Boolean.class))
|
||||||
|
{
|
||||||
|
return (BOOLEAN);
|
||||||
|
}
|
||||||
if(c.equals(BigDecimal.class))
|
if(c.equals(BigDecimal.class))
|
||||||
{
|
{
|
||||||
return (DECIMAL);
|
return (DECIMAL);
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.metadata.frontend;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public enum AppTreeNodeType
|
||||||
|
{
|
||||||
|
TABLE,
|
||||||
|
PROCESS,
|
||||||
|
APP
|
||||||
|
}
|
@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.metadata.frontend;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppChildMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Version of QAppMetaData that's meant for transmitting to a frontend.
|
||||||
|
*
|
||||||
|
*******************************************************************************/
|
||||||
|
@JsonInclude(Include.NON_NULL)
|
||||||
|
public class QFrontendAppMetaData
|
||||||
|
{
|
||||||
|
private AppTreeNodeType type;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String label;
|
||||||
|
|
||||||
|
private List<QFrontendAppMetaData> children = new ArrayList<>();
|
||||||
|
|
||||||
|
private String iconName;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QFrontendAppMetaData(QAppChildMetaData appChildMetaData)
|
||||||
|
{
|
||||||
|
this.name = appChildMetaData.getName();
|
||||||
|
this.label = appChildMetaData.getLabel();
|
||||||
|
|
||||||
|
if(appChildMetaData.getClass().equals(QTableMetaData.class))
|
||||||
|
{
|
||||||
|
this.type = AppTreeNodeType.TABLE;
|
||||||
|
}
|
||||||
|
else if(appChildMetaData.getClass().equals(QProcessMetaData.class))
|
||||||
|
{
|
||||||
|
this.type = AppTreeNodeType.PROCESS;
|
||||||
|
}
|
||||||
|
else if(appChildMetaData.getClass().equals(QAppMetaData.class))
|
||||||
|
{
|
||||||
|
this.type = AppTreeNodeType.APP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw (new IllegalStateException("Unrecognized class for app child meta data: " + appChildMetaData.getClass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(appChildMetaData.getIcon() != null && StringUtils.hasContent(appChildMetaData.getIcon().getName()))
|
||||||
|
{
|
||||||
|
this.iconName = appChildMetaData.getIcon().getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for name
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for label
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getLabel()
|
||||||
|
{
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for type
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public AppTreeNodeType getType()
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for children
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public List<QFrontendAppMetaData> getChildren()
|
||||||
|
{
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for iconName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getIconName()
|
||||||
|
{
|
||||||
|
return iconName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for iconName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setIconName(String iconName)
|
||||||
|
{
|
||||||
|
this.iconName = iconName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void addChild(QFrontendAppMetaData qFrontendAppMetaData)
|
||||||
|
{
|
||||||
|
if(children == null)
|
||||||
|
{
|
||||||
|
children = new ArrayList<>();
|
||||||
|
}
|
||||||
|
children.add(qFrontendAppMetaData);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.metadata.layout;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Interface shared by meta-data objects which can be placed into an App.
|
||||||
|
*******************************************************************************/
|
||||||
|
public interface QAppChildMetaData
|
||||||
|
{
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
void setParentAppName(String parentAppName);
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
String getParentAppName();
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
String getLabel();
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
default QIcon getIcon()
|
||||||
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.metadata.layout;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class QAppMetaData implements QAppChildMetaData
|
||||||
|
{
|
||||||
|
private String name;
|
||||||
|
private String label;
|
||||||
|
|
||||||
|
private List<QAppChildMetaData> children;
|
||||||
|
|
||||||
|
private String parentAppName;
|
||||||
|
private QIcon icon;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QAppMetaData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for name
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for name
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setName(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for name
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QAppMetaData withName(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for label
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getLabel()
|
||||||
|
{
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for label
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setLabel(String label)
|
||||||
|
{
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for label
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QAppMetaData withLabel(String label)
|
||||||
|
{
|
||||||
|
this.label = label;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for children
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public List<QAppChildMetaData> getChildren()
|
||||||
|
{
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for children
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setChildren(List<QAppChildMetaData> children)
|
||||||
|
{
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Add a child to this app.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void addChild(QAppChildMetaData child)
|
||||||
|
{
|
||||||
|
if(this.children == null)
|
||||||
|
{
|
||||||
|
this.children = new ArrayList<>();
|
||||||
|
}
|
||||||
|
this.children.add(child);
|
||||||
|
child.setParentAppName(this.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluently add a child to this app.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QAppMetaData withChild(QAppChildMetaData child)
|
||||||
|
{
|
||||||
|
addChild(child);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for children
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QAppMetaData withChildren(List<QAppChildMetaData> children)
|
||||||
|
{
|
||||||
|
this.children = children;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for parentAppName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public String getParentAppName()
|
||||||
|
{
|
||||||
|
return parentAppName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for parentAppName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public void setParentAppName(String parentAppName)
|
||||||
|
{
|
||||||
|
this.parentAppName = parentAppName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for icon
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QIcon getIcon()
|
||||||
|
{
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for icon
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setIcon(QIcon icon)
|
||||||
|
{
|
||||||
|
this.icon = icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for icon
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QAppMetaData withIcon(QIcon icon)
|
||||||
|
{
|
||||||
|
this.icon = icon;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2022. Kingsrook, LLC
|
||||||
|
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||||
|
* contact@kingsrook.com
|
||||||
|
* https://github.com/Kingsrook/
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.backend.core.model.metadata.layout;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Icon to show associated with an App, Table, Process, etc.
|
||||||
|
**
|
||||||
|
** Currently, name here must be a reference from https://fonts.google.com/icons
|
||||||
|
** e.g., local_shipping for https://fonts.google.com/icons?selected=Material+Symbols+Outlined:local_shipping
|
||||||
|
**
|
||||||
|
** Future may allow something like a "namespace", and/or multiple icons for
|
||||||
|
** use in different frontends, etc.
|
||||||
|
*******************************************************************************/
|
||||||
|
public class QIcon
|
||||||
|
{
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QIcon()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QIcon(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for name
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for name
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setName(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for name
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QIcon withName(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -26,13 +26,15 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppChildMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Meta-Data to define a process in a QQQ instance.
|
** Meta-Data to define a process in a QQQ instance.
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class QProcessMetaData
|
public class QProcessMetaData implements QAppChildMetaData
|
||||||
{
|
{
|
||||||
private String name;
|
private String name;
|
||||||
private String label;
|
private String label;
|
||||||
@ -41,6 +43,8 @@ public class QProcessMetaData
|
|||||||
|
|
||||||
private List<QStepMetaData> stepList;
|
private List<QStepMetaData> stepList;
|
||||||
|
|
||||||
|
private String parentAppName;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -293,4 +297,28 @@ public class QProcessMetaData
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for parentAppName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public String getParentAppName()
|
||||||
|
{
|
||||||
|
return parentAppName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for parentAppName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public void setParentAppName(String parentAppName)
|
||||||
|
{
|
||||||
|
this.parentAppName = parentAppName;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,13 +30,15 @@ import java.util.Map;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppChildMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QIcon;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Meta-Data to define a table in a QQQ instance.
|
** Meta-Data to define a table in a QQQ instance.
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class QTableMetaData implements Serializable
|
public class QTableMetaData implements QAppChildMetaData, Serializable
|
||||||
{
|
{
|
||||||
private String name;
|
private String name;
|
||||||
private String label;
|
private String label;
|
||||||
@ -59,6 +61,8 @@ public class QTableMetaData implements Serializable
|
|||||||
|
|
||||||
private Map<String, QCodeReference> customizers;
|
private Map<String, QCodeReference> customizers;
|
||||||
|
|
||||||
|
private String parentAppName;
|
||||||
|
private QIcon icon;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -434,4 +438,72 @@ public class QTableMetaData implements Serializable
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QTableMetaData withInferredFieldBackendNames()
|
||||||
|
{
|
||||||
|
// todo not commit QInstanceEnricher.setInferredFieldBackendNames(this);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for parentAppName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public String getParentAppName()
|
||||||
|
{
|
||||||
|
return parentAppName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for parentAppName
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public void setParentAppName(String parentAppName)
|
||||||
|
{
|
||||||
|
this.parentAppName = parentAppName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for icon
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QIcon getIcon()
|
||||||
|
{
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for icon
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setIcon(QIcon icon)
|
||||||
|
{
|
||||||
|
this.icon = icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for icon
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QTableMetaData withIcon(QIcon icon)
|
||||||
|
{
|
||||||
|
this.icon = icon;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,7 @@ public class MockQueryAction implements QueryInterface
|
|||||||
{
|
{
|
||||||
Serializable value = field.equals("id") ? (i + 1) : getValue(table, field);
|
Serializable value = field.equals("id") ? (i + 1) : getValue(table, field);
|
||||||
record.setValue(field, value);
|
record.setValue(field, value);
|
||||||
|
record.setDisplayValue(table.getField(field), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
queryOutput.addRecord(record);
|
queryOutput.addRecord(record);
|
||||||
|
@ -22,12 +22,20 @@
|
|||||||
package com.kingsrook.qqq.backend.core.actions.metadata;
|
package com.kingsrook.qqq.backend.core.actions.metadata;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput;
|
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendAppMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -47,9 +55,66 @@ class MetaDataActionTest
|
|||||||
request.setSession(TestUtils.getMockSession());
|
request.setSession(TestUtils.getMockSession());
|
||||||
MetaDataOutput result = new MetaDataAction().execute(request);
|
MetaDataOutput result = new MetaDataAction().execute(request);
|
||||||
assertNotNull(result);
|
assertNotNull(result);
|
||||||
|
|
||||||
|
///////////////////////////////////
|
||||||
|
// assert against the tables map //
|
||||||
|
///////////////////////////////////
|
||||||
assertNotNull(result.getTables());
|
assertNotNull(result.getTables());
|
||||||
assertNotNull(result.getTables().get("person"));
|
assertNotNull(result.getTables().get("person"));
|
||||||
assertEquals("person", result.getTables().get("person").getName());
|
assertEquals("person", result.getTables().get("person").getName());
|
||||||
assertEquals("Person", result.getTables().get("person").getLabel());
|
assertEquals("Person", result.getTables().get("person").getLabel());
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
// assert against the processes map //
|
||||||
|
//////////////////////////////////////
|
||||||
|
assertNotNull(result.getProcesses().get("greet"));
|
||||||
|
assertNotNull(result.getProcesses().get("greetInteractive"));
|
||||||
|
assertNotNull(result.getProcesses().get("etl.basic"));
|
||||||
|
assertNotNull(result.getProcesses().get("person.bulkInsert"));
|
||||||
|
assertNotNull(result.getProcesses().get("person.bulkEdit"));
|
||||||
|
assertNotNull(result.getProcesses().get("person.bulkDelete"));
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// assert against the apps map - which is appName to app - but not fully hierarchical - that's appTree //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Map<String, QFrontendAppMetaData> apps = result.getApps();
|
||||||
|
assertNotNull(apps.get(TestUtils.APP_NAME_GREETINGS));
|
||||||
|
assertNotNull(apps.get(TestUtils.APP_NAME_PEOPLE));
|
||||||
|
assertNotNull(apps.get(TestUtils.APP_NAME_MISCELLANEOUS));
|
||||||
|
|
||||||
|
QFrontendAppMetaData peopleApp = apps.get(TestUtils.APP_NAME_PEOPLE);
|
||||||
|
assertThat(peopleApp.getChildren()).isNotEmpty();
|
||||||
|
Optional<QFrontendAppMetaData> greetingsAppUnderPeopleFromMapOptional = peopleApp.getChildren().stream()
|
||||||
|
.filter(e -> e.getName().equals(TestUtils.APP_NAME_GREETINGS)).findFirst();
|
||||||
|
assertThat(greetingsAppUnderPeopleFromMapOptional).isPresent();
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// we want to show that in the appMap (e.g., "apps"), that the apps are not //
|
||||||
|
// hierarchical - that is - that a sub-app doesn't list ITS children here. //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
assertThat(greetingsAppUnderPeopleFromMapOptional.get().getChildren()).isNullOrEmpty();
|
||||||
|
|
||||||
|
///////////////////////////////////////////////
|
||||||
|
// assert against the hierarchical apps tree //
|
||||||
|
///////////////////////////////////////////////
|
||||||
|
List<QFrontendAppMetaData> appTree = result.getAppTree();
|
||||||
|
Set<String> appNamesInTopOfTree = appTree.stream().map(QFrontendAppMetaData::getName).collect(Collectors.toSet());
|
||||||
|
assertThat(appNamesInTopOfTree).contains(TestUtils.APP_NAME_PEOPLE);
|
||||||
|
assertThat(appNamesInTopOfTree).contains(TestUtils.APP_NAME_MISCELLANEOUS);
|
||||||
|
assertThat(appNamesInTopOfTree).doesNotContain(TestUtils.APP_NAME_GREETINGS);
|
||||||
|
|
||||||
|
Optional<QFrontendAppMetaData> peopleAppOptional = appTree.stream()
|
||||||
|
.filter(e -> e.getName().equals(TestUtils.APP_NAME_PEOPLE)).findFirst();
|
||||||
|
assertThat(peopleAppOptional).isPresent();
|
||||||
|
assertThat(peopleAppOptional.get().getChildren()).isNotEmpty();
|
||||||
|
|
||||||
|
Optional<QFrontendAppMetaData> greetingsAppUnderPeopleFromTree = peopleAppOptional.get().getChildren().stream()
|
||||||
|
.filter(e -> e.getName().equals(TestUtils.APP_NAME_GREETINGS)).findFirst();
|
||||||
|
assertThat(greetingsAppUnderPeopleFromTree).isPresent();
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// but here, when this app comes from the tree, then it DOES have its children //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
assertThat(greetingsAppUnderPeopleFromTree.get().getChildren()).isNotEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,10 @@ package com.kingsrook.qqq.backend.core.actions.tables;
|
|||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
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.utils.TestUtils;
|
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
|
|
||||||
@ -50,5 +52,13 @@ class QueryActionTest
|
|||||||
request.setTableName("person");
|
request.setTableName("person");
|
||||||
QueryOutput result = new QueryAction().execute(request);
|
QueryOutput result = new QueryAction().execute(request);
|
||||||
assertNotNull(result);
|
assertNotNull(result);
|
||||||
|
|
||||||
|
assertThat(result.getRecords()).isNotEmpty();
|
||||||
|
for(QRecord record : result.getRecords())
|
||||||
|
{
|
||||||
|
assertThat(record.getValues()).isNotEmpty();
|
||||||
|
assertThat(record.getDisplayValues()).isNotEmpty();
|
||||||
|
assertThat(record.getErrors()).isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,17 @@
|
|||||||
package com.kingsrook.qqq.backend.core.instances;
|
package com.kingsrook.qqq.backend.core.instances;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
import com.kingsrook.qqq.backend.core.utils.TestUtils;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
|
||||||
@ -51,6 +55,21 @@ class QInstanceValidatorTest
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** make sure we don't re-validate if already validated
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
public void test_doNotReValidate() throws QInstanceValidationException
|
||||||
|
{
|
||||||
|
QInstance qInstance = TestUtils.defineInstance();
|
||||||
|
qInstance.setHasBeenValidated(new QInstanceValidationKey());
|
||||||
|
qInstance.setBackends(null);
|
||||||
|
new QInstanceValidator().validate(qInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Test an instance with null backends - should throw.
|
** Test an instance with null backends - should throw.
|
||||||
**
|
**
|
||||||
@ -58,17 +77,8 @@ class QInstanceValidatorTest
|
|||||||
@Test
|
@Test
|
||||||
public void test_validateNullBackends()
|
public void test_validateNullBackends()
|
||||||
{
|
{
|
||||||
try
|
assertValidationFailureReasons((qInstance) -> qInstance.setBackends(null),
|
||||||
{
|
"At least 1 backend must be defined");
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
|
||||||
qInstance.setBackends(null);
|
|
||||||
new QInstanceValidator().validate(qInstance);
|
|
||||||
fail("Should have thrown validationException");
|
|
||||||
}
|
|
||||||
catch(QInstanceValidationException e)
|
|
||||||
{
|
|
||||||
assertReason("At least 1 backend must be defined", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -80,17 +90,8 @@ class QInstanceValidatorTest
|
|||||||
@Test
|
@Test
|
||||||
public void test_validateEmptyBackends()
|
public void test_validateEmptyBackends()
|
||||||
{
|
{
|
||||||
try
|
assertValidationFailureReasons((qInstance) -> qInstance.setBackends(new HashMap<>()),
|
||||||
{
|
"At least 1 backend must be defined");
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
|
||||||
qInstance.setBackends(new HashMap<>());
|
|
||||||
new QInstanceValidator().validate(qInstance);
|
|
||||||
fail("Should have thrown validationException");
|
|
||||||
}
|
|
||||||
catch(QInstanceValidationException e)
|
|
||||||
{
|
|
||||||
assertReason("At least 1 backend must be defined", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -102,17 +103,12 @@ class QInstanceValidatorTest
|
|||||||
@Test
|
@Test
|
||||||
public void test_validateNullTables()
|
public void test_validateNullTables()
|
||||||
{
|
{
|
||||||
try
|
assertValidationFailureReasons((qInstance) ->
|
||||||
{
|
{
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
qInstance.setTables(null);
|
||||||
qInstance.setTables(null);
|
qInstance.setProcesses(null);
|
||||||
new QInstanceValidator().validate(qInstance);
|
},
|
||||||
fail("Should have thrown validationException");
|
"At least 1 table must be defined");
|
||||||
}
|
|
||||||
catch(QInstanceValidationException e)
|
|
||||||
{
|
|
||||||
assertReason("At least 1 table must be defined", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -124,17 +120,12 @@ class QInstanceValidatorTest
|
|||||||
@Test
|
@Test
|
||||||
public void test_validateEmptyTables()
|
public void test_validateEmptyTables()
|
||||||
{
|
{
|
||||||
try
|
assertValidationFailureReasons((qInstance) ->
|
||||||
{
|
{
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
qInstance.setTables(new HashMap<>());
|
||||||
qInstance.setTables(new HashMap<>());
|
qInstance.setProcesses(new HashMap<>());
|
||||||
new QInstanceValidator().validate(qInstance);
|
},
|
||||||
fail("Should have thrown validationException");
|
"At least 1 table must be defined");
|
||||||
}
|
|
||||||
catch(QInstanceValidationException e)
|
|
||||||
{
|
|
||||||
assertReason("At least 1 table must be defined", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -147,19 +138,15 @@ class QInstanceValidatorTest
|
|||||||
@Test
|
@Test
|
||||||
public void test_validateInconsistentNames()
|
public void test_validateInconsistentNames()
|
||||||
{
|
{
|
||||||
try
|
assertValidationFailureReasonsAllowingExtraReasons((qInstance) ->
|
||||||
{
|
{
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
qInstance.getTable("person").setName("notPerson");
|
||||||
qInstance.getTable("person").setName("notPerson");
|
qInstance.getBackend("default").setName("notDefault");
|
||||||
qInstance.getBackend("default").setName("notDefault");
|
qInstance.getProcess(TestUtils.PROCESS_NAME_GREET_PEOPLE).setName("notGreetPeople");
|
||||||
new QInstanceValidator().validate(qInstance);
|
},
|
||||||
fail("Should have thrown validationException");
|
"Inconsistent naming for table",
|
||||||
}
|
"Inconsistent naming for backend",
|
||||||
catch(QInstanceValidationException e)
|
"Inconsistent naming for process");
|
||||||
{
|
|
||||||
assertReason("Inconsistent naming for table", e);
|
|
||||||
assertReason("Inconsistent naming for backend", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -171,17 +158,8 @@ class QInstanceValidatorTest
|
|||||||
@Test
|
@Test
|
||||||
public void test_validateTableWithoutBackend()
|
public void test_validateTableWithoutBackend()
|
||||||
{
|
{
|
||||||
try
|
assertValidationFailureReasons((qInstance) -> qInstance.getTable("person").setBackendName(null),
|
||||||
{
|
"Missing backend name for table");
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
|
||||||
qInstance.getTable("person").setBackendName(null);
|
|
||||||
new QInstanceValidator().validate(qInstance);
|
|
||||||
fail("Should have thrown validationException");
|
|
||||||
}
|
|
||||||
catch(QInstanceValidationException e)
|
|
||||||
{
|
|
||||||
assertReason("Missing backend name for table", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -193,17 +171,53 @@ class QInstanceValidatorTest
|
|||||||
@Test
|
@Test
|
||||||
public void test_validateTableWithMissingBackend()
|
public void test_validateTableWithMissingBackend()
|
||||||
{
|
{
|
||||||
try
|
assertValidationFailureReasons((qInstance) -> qInstance.getTable("person").setBackendName("notARealBackend"),
|
||||||
{
|
"Unrecognized backend");
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
}
|
||||||
qInstance.getTable("person").setBackendName("notARealBackend");
|
|
||||||
new QInstanceValidator().validate(qInstance);
|
|
||||||
fail("Should have thrown validationException");
|
|
||||||
}
|
/*******************************************************************************
|
||||||
catch(QInstanceValidationException e)
|
** Test that if a process specifies a table that doesn't exist, that it fails.
|
||||||
{
|
**
|
||||||
assertReason("Unrecognized backend", e);
|
*******************************************************************************/
|
||||||
}
|
@Test
|
||||||
|
public void test_validateProcessWithMissingTable()
|
||||||
|
{
|
||||||
|
assertValidationFailureReasons((qInstance) -> qInstance.getProcess(TestUtils.PROCESS_NAME_GREET_PEOPLE).setTableName("notATableName"),
|
||||||
|
"Unrecognized table");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Test that a process with no steps fails
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
public void test_validateProcessWithNoSteps()
|
||||||
|
{
|
||||||
|
assertValidationFailureReasons((qInstance) -> qInstance.getProcess(TestUtils.PROCESS_NAME_GREET_PEOPLE).setStepList(Collections.emptyList()),
|
||||||
|
"At least 1 step");
|
||||||
|
|
||||||
|
assertValidationFailureReasons((qInstance) -> qInstance.getProcess(TestUtils.PROCESS_NAME_GREET_PEOPLE).setStepList(null),
|
||||||
|
"At least 1 step");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Test that a process step with an empty string name fails
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
public void test_validateProcessStepWithEmptyName()
|
||||||
|
{
|
||||||
|
assertValidationFailureReasons((qInstance) -> qInstance.getProcess(TestUtils.PROCESS_NAME_GREET_PEOPLE).getStepList().get(0).setName(""),
|
||||||
|
"Missing name for a step");
|
||||||
|
|
||||||
|
assertValidationFailureReasons((qInstance) -> qInstance.getProcess(TestUtils.PROCESS_NAME_GREET_PEOPLE_INTERACTIVE).getStepList().get(1).setName(null),
|
||||||
|
"Missing name for a step");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -215,29 +229,11 @@ class QInstanceValidatorTest
|
|||||||
@Test
|
@Test
|
||||||
public void test_validateTableWithNoFields()
|
public void test_validateTableWithNoFields()
|
||||||
{
|
{
|
||||||
try
|
assertValidationFailureReasons((qInstance) -> qInstance.getTable("person").setFields(null),
|
||||||
{
|
"At least 1 field");
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
|
||||||
qInstance.getTable("person").setFields(null);
|
|
||||||
new QInstanceValidator().validate(qInstance);
|
|
||||||
fail("Should have thrown validationException");
|
|
||||||
}
|
|
||||||
catch(QInstanceValidationException e)
|
|
||||||
{
|
|
||||||
assertReason("At least 1 field", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
assertValidationFailureReasons((qInstance) -> qInstance.getTable("person").setFields(new HashMap<>()),
|
||||||
{
|
"At least 1 field");
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
|
||||||
qInstance.getTable("person").setFields(new HashMap<>());
|
|
||||||
new QInstanceValidator().validate(qInstance);
|
|
||||||
fail("Should have thrown validationException");
|
|
||||||
}
|
|
||||||
catch(QInstanceValidationException e)
|
|
||||||
{
|
|
||||||
assertReason("At least 1 field", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -248,17 +244,92 @@ class QInstanceValidatorTest
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@Test
|
@Test
|
||||||
public void test_validateFieldWithMissingPossibleValueSource()
|
public void test_validateFieldWithMissingPossibleValueSource()
|
||||||
|
{
|
||||||
|
assertValidationFailureReasons((qInstance) -> qInstance.getTable("person").getField("homeState").setPossibleValueSourceName("not a real possible value source"),
|
||||||
|
"Unrecognized possibleValueSourceName");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testChildrenWithBadParentAppName()
|
||||||
|
{
|
||||||
|
String[] reasons = new String[] { "Unrecognized parent app", "does not have its parent app properly set" };
|
||||||
|
assertValidationFailureReasons((qInstance) -> qInstance.getTable(TestUtils.TABLE_NAME_PERSON).setParentAppName("notAnApp"), reasons);
|
||||||
|
assertValidationFailureReasons((qInstance) -> qInstance.getProcess(TestUtils.PROCESS_NAME_GREET_PEOPLE).setParentAppName("notAnApp"), reasons);
|
||||||
|
assertValidationFailureReasons((qInstance) -> qInstance.getApp(TestUtils.APP_NAME_GREETINGS).setParentAppName("notAnApp"), reasons);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testAppCircularReferences()
|
||||||
|
{
|
||||||
|
assertValidationFailureReasonsAllowingExtraReasons((qInstance) ->
|
||||||
|
{
|
||||||
|
QAppMetaData miscApp = qInstance.getApp(TestUtils.APP_NAME_MISCELLANEOUS);
|
||||||
|
QAppMetaData greetingsApp = qInstance.getApp(TestUtils.APP_NAME_GREETINGS);
|
||||||
|
|
||||||
|
miscApp.withChild(greetingsApp);
|
||||||
|
greetingsApp.withChild(miscApp);
|
||||||
|
}, "Circular app reference");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Run a little setup code on a qInstance; then validate it, and assert that it
|
||||||
|
** failed validation with reasons that match the supplied vararg-reasons (but allow
|
||||||
|
** more reasons - e.g., helpful when one thing we're testing causes other errors).
|
||||||
|
*******************************************************************************/
|
||||||
|
private void assertValidationFailureReasonsAllowingExtraReasons(Consumer<QInstance> setup, String... reasons)
|
||||||
|
{
|
||||||
|
assertValidationFailureReasons(setup, true, reasons);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Run a little setup code on a qInstance; then validate it, and assert that it
|
||||||
|
** failed validation with reasons that match the supplied vararg-reasons (and
|
||||||
|
** require that exact # of reasons).
|
||||||
|
*******************************************************************************/
|
||||||
|
private void assertValidationFailureReasons(Consumer<QInstance> setup, String... reasons)
|
||||||
|
{
|
||||||
|
assertValidationFailureReasons(setup, false, reasons);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Implementation for the overloads of this name.
|
||||||
|
*******************************************************************************/
|
||||||
|
private void assertValidationFailureReasons(Consumer<QInstance> setup, boolean allowExtraReasons, String... reasons)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
QInstance qInstance = TestUtils.defineInstance();
|
QInstance qInstance = TestUtils.defineInstance();
|
||||||
qInstance.getTable("person").getField("homeState").setPossibleValueSourceName("not a real possible value source");
|
setup.accept(qInstance);
|
||||||
new QInstanceValidator().validate(qInstance);
|
new QInstanceValidator().validate(qInstance);
|
||||||
fail("Should have thrown validationException");
|
fail("Should have thrown validationException");
|
||||||
}
|
}
|
||||||
catch(QInstanceValidationException e)
|
catch(QInstanceValidationException e)
|
||||||
{
|
{
|
||||||
assertReason("Unrecognized possibleValueSourceName", e);
|
if(!allowExtraReasons)
|
||||||
|
{
|
||||||
|
assertEquals(reasons.length, e.getReasons().size(), "Expected number of validation failure reasons\nExpected: " + String.join(",", reasons) + "\nActual: " + e.getReasons());
|
||||||
|
}
|
||||||
|
|
||||||
|
for(String reason : reasons)
|
||||||
|
{
|
||||||
|
assertReason(reason, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,7 +342,9 @@ class QInstanceValidatorTest
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
private void assertReason(String reason, QInstanceValidationException e)
|
private void assertReason(String reason, QInstanceValidationException e)
|
||||||
{
|
{
|
||||||
assertNotNull(e.getReasons());
|
assertNotNull(e.getReasons(), "Expected there to be a reason for the failure (but there was not)");
|
||||||
assertTrue(e.getReasons().stream().anyMatch(s -> s.contains(reason)));
|
assertThat(e.getReasons())
|
||||||
|
.withFailMessage("Expected any of:\n%s\nTo match: [%s]", e.getReasons(), reason)
|
||||||
|
.anyMatch(s -> s.contains(reason));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
|||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSource;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSourceType;
|
import com.kingsrook.qqq.backend.core.model.metadata.possiblevalues.QPossibleValueSourceType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
||||||
@ -62,9 +63,19 @@ import com.kingsrook.qqq.backend.core.processes.implementations.etl.basic.BasicE
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class TestUtils
|
public class TestUtils
|
||||||
{
|
{
|
||||||
public static String DEFAULT_BACKEND_NAME = "default";
|
public static final String DEFAULT_BACKEND_NAME = "default";
|
||||||
public static String PROCESS_NAME_GREET_PEOPLE = "greet";
|
|
||||||
public static String PROCESS_NAME_GREET_PEOPLE_INTERACTIVE = "greetInteractive";
|
public static final String APP_NAME_GREETINGS = "greetingsApp";
|
||||||
|
public static final String APP_NAME_PEOPLE = "peopleApp";
|
||||||
|
public static final String APP_NAME_MISCELLANEOUS = "miscellaneous";
|
||||||
|
|
||||||
|
public static final String TABLE_NAME_PERSON = "person";
|
||||||
|
|
||||||
|
public static final String PROCESS_NAME_GREET_PEOPLE = "greet";
|
||||||
|
public static final String PROCESS_NAME_GREET_PEOPLE_INTERACTIVE = "greetInteractive";
|
||||||
|
public static final String PROCESS_NAME_ADD_TO_PEOPLES_AGE = "addToPeoplesAge";
|
||||||
|
public static final String TABLE_NAME_PERSON_FILE = "personFile";
|
||||||
|
public static final String TABLE_NAME_ID_AND_NAME_ONLY = "idAndNameOnly";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -77,15 +88,20 @@ public class TestUtils
|
|||||||
QInstance qInstance = new QInstance();
|
QInstance qInstance = new QInstance();
|
||||||
qInstance.setAuthentication(defineAuthentication());
|
qInstance.setAuthentication(defineAuthentication());
|
||||||
qInstance.addBackend(defineBackend());
|
qInstance.addBackend(defineBackend());
|
||||||
|
|
||||||
qInstance.addTable(defineTablePerson());
|
qInstance.addTable(defineTablePerson());
|
||||||
qInstance.addTable(definePersonFileTable());
|
qInstance.addTable(definePersonFileTable());
|
||||||
qInstance.addTable(defineTableIdAndNameOnly());
|
qInstance.addTable(defineTableIdAndNameOnly());
|
||||||
|
|
||||||
qInstance.addPossibleValueSource(defineStatesPossibleValueSource());
|
qInstance.addPossibleValueSource(defineStatesPossibleValueSource());
|
||||||
|
|
||||||
qInstance.addProcess(defineProcessGreetPeople());
|
qInstance.addProcess(defineProcessGreetPeople());
|
||||||
qInstance.addProcess(defineProcessGreetPeopleInteractive());
|
qInstance.addProcess(defineProcessGreetPeopleInteractive());
|
||||||
qInstance.addProcess(defineProcessAddToPeoplesAge());
|
qInstance.addProcess(defineProcessAddToPeoplesAge());
|
||||||
qInstance.addProcess(new BasicETLProcess().defineProcessMetaData());
|
qInstance.addProcess(new BasicETLProcess().defineProcessMetaData());
|
||||||
|
|
||||||
|
defineApps(qInstance);
|
||||||
|
|
||||||
System.out.println(new QInstanceAdapter().qInstanceToJson(qInstance));
|
System.out.println(new QInstanceAdapter().qInstanceToJson(qInstance));
|
||||||
|
|
||||||
return (qInstance);
|
return (qInstance);
|
||||||
@ -93,6 +109,30 @@ public class TestUtils
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static void defineApps(QInstance qInstance)
|
||||||
|
{
|
||||||
|
qInstance.addApp(new QAppMetaData()
|
||||||
|
.withName(APP_NAME_GREETINGS)
|
||||||
|
.withChild(qInstance.getProcess(PROCESS_NAME_GREET_PEOPLE))
|
||||||
|
.withChild(qInstance.getProcess(PROCESS_NAME_GREET_PEOPLE_INTERACTIVE)));
|
||||||
|
|
||||||
|
qInstance.addApp(new QAppMetaData()
|
||||||
|
.withName(APP_NAME_PEOPLE)
|
||||||
|
.withChild(qInstance.getTable(TABLE_NAME_PERSON))
|
||||||
|
.withChild(qInstance.getTable(TABLE_NAME_PERSON_FILE))
|
||||||
|
.withChild(qInstance.getApp(APP_NAME_GREETINGS)));
|
||||||
|
|
||||||
|
qInstance.addApp(new QAppMetaData()
|
||||||
|
.withName(APP_NAME_MISCELLANEOUS)
|
||||||
|
.withChild(qInstance.getTable(TABLE_NAME_ID_AND_NAME_ONLY))
|
||||||
|
.withChild(qInstance.getProcess(BasicETLProcess.PROCESS_NAME)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Define the "states" possible value source used in standard tests
|
** Define the "states" possible value source used in standard tests
|
||||||
**
|
**
|
||||||
|
@ -46,10 +46,12 @@ import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
|||||||
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
||||||
import com.kingsrook.qqq.backend.core.adapters.QInstanceAdapter;
|
import com.kingsrook.qqq.backend.core.adapters.QInstanceAdapter;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QAuthenticationException;
|
import com.kingsrook.qqq.backend.core.exceptions.QAuthenticationException;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QModuleDispatchException;
|
import com.kingsrook.qqq.backend.core.exceptions.QModuleDispatchException;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
import com.kingsrook.qqq.backend.core.exceptions.QNotFoundException;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
import com.kingsrook.qqq.backend.core.exceptions.QUserFacingException;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QValueException;
|
import com.kingsrook.qqq.backend.core.exceptions.QValueException;
|
||||||
|
import com.kingsrook.qqq.backend.core.instances.QInstanceValidator;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionInput;
|
import com.kingsrook.qqq.backend.core.model.actions.AbstractActionInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput;
|
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataInput;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput;
|
import com.kingsrook.qqq.backend.core.model.actions.metadata.MetaDataOutput;
|
||||||
@ -121,7 +123,7 @@ public class QJavalinImplementation
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static void main(String[] args)
|
public static void main(String[] args) throws QInstanceValidationException
|
||||||
{
|
{
|
||||||
QInstance qInstance = new QInstance();
|
QInstance qInstance = new QInstance();
|
||||||
// todo - parse args to look up metaData and prime instance
|
// todo - parse args to look up metaData and prime instance
|
||||||
@ -135,9 +137,10 @@ public class QJavalinImplementation
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public QJavalinImplementation(QInstance qInstance)
|
public QJavalinImplementation(QInstance qInstance) throws QInstanceValidationException
|
||||||
{
|
{
|
||||||
QJavalinImplementation.qInstance = qInstance;
|
QJavalinImplementation.qInstance = qInstance;
|
||||||
|
new QInstanceValidator().validate(qInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
package com.kingsrook.qqq.backend.javalin;
|
package com.kingsrook.qqq.backend.javalin;
|
||||||
|
|
||||||
|
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
@ -44,7 +45,7 @@ public class QJavalinTestBase
|
|||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void beforeAll()
|
public static void beforeAll() throws QInstanceValidationException
|
||||||
{
|
{
|
||||||
qJavalinImplementation = new QJavalinImplementation(TestUtils.defineInstance());
|
qJavalinImplementation = new QJavalinImplementation(TestUtils.defineInstance());
|
||||||
QJavalinProcessHandler.setAsyncStepTimeoutMillis(250);
|
QJavalinProcessHandler.setAsyncStepTimeoutMillis(250);
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
package com.kingsrook.sampleapp;
|
package com.kingsrook.sampleapp;
|
||||||
|
|
||||||
|
|
||||||
|
import com.kingsrook.qqq.backend.core.instances.QInstanceValidator;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
import com.kingsrook.qqq.backend.javalin.QJavalinImplementation;
|
import com.kingsrook.qqq.backend.javalin.QJavalinImplementation;
|
||||||
import io.javalin.Javalin;
|
import io.javalin.Javalin;
|
||||||
|
@ -29,13 +29,13 @@ import com.kingsrook.qqq.backend.core.exceptions.QValueException;
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.processes.RunBackendStepInput;
|
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.processes.RunBackendStepOutput;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationType;
|
import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeUsage;
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeUsage;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.layout.QAppMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QBackendStepMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFrontendStepMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMetaData;
|
||||||
@ -59,7 +59,7 @@ import io.github.cdimascio.dotenv.Dotenv;
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class SampleMetaDataProvider
|
public class SampleMetaDataProvider
|
||||||
{
|
{
|
||||||
public static boolean USE_MYSQL = false;
|
public static boolean USE_MYSQL = true;
|
||||||
|
|
||||||
public static final String RDBMS_BACKEND_NAME = "rdbms";
|
public static final String RDBMS_BACKEND_NAME = "rdbms";
|
||||||
public static final String FILESYSTEM_BACKEND_NAME = "filesystem";
|
public static final String FILESYSTEM_BACKEND_NAME = "filesystem";
|
||||||
@ -68,12 +68,20 @@ public class SampleMetaDataProvider
|
|||||||
// public static final String AUTH0_BASE_URL = "https://kingsrook.us.auth0.com/";
|
// public static final String AUTH0_BASE_URL = "https://kingsrook.us.auth0.com/";
|
||||||
public static final String AUTH0_BASE_URL = "https://nutrifresh-one-development.us.auth0.com/";
|
public static final String AUTH0_BASE_URL = "https://nutrifresh-one-development.us.auth0.com/";
|
||||||
|
|
||||||
|
public static final String APP_NAME_GREETINGS = "greetingsApp";
|
||||||
|
public static final String APP_NAME_PEOPLE = "peopleApp";
|
||||||
|
public static final String APP_NAME_MISCELLANEOUS = "miscellaneous";
|
||||||
|
|
||||||
public static final String PROCESS_NAME_GREET = "greet";
|
public static final String PROCESS_NAME_GREET = "greet";
|
||||||
public static final String PROCESS_NAME_GREET_INTERACTIVE = "greetInteractive";
|
public static final String PROCESS_NAME_GREET_INTERACTIVE = "greetInteractive";
|
||||||
public static final String PROCESS_NAME_SIMPLE_SLEEP = "simpleSleep";
|
public static final String PROCESS_NAME_SIMPLE_SLEEP = "simpleSleep";
|
||||||
public static final String PROCESS_NAME_SIMPLE_THROW = "simpleThrow";
|
public static final String PROCESS_NAME_SIMPLE_THROW = "simpleThrow";
|
||||||
public static final String PROCESS_NAME_SLEEP_INTERACTIVE = "sleepInteractive";
|
public static final String PROCESS_NAME_SLEEP_INTERACTIVE = "sleepInteractive";
|
||||||
|
|
||||||
|
public static final String TABLE_NAME_PERSON = "person";
|
||||||
|
public static final String TABLE_NAME_CARRIER = "carrier";
|
||||||
|
public static final String TABLE_NAME_CITY = "city";
|
||||||
|
|
||||||
public static final String STEP_NAME_SLEEPER = "sleeper";
|
public static final String STEP_NAME_SLEEPER = "sleeper";
|
||||||
public static final String STEP_NAME_THROWER = "thrower";
|
public static final String STEP_NAME_THROWER = "thrower";
|
||||||
|
|
||||||
@ -101,11 +109,39 @@ public class SampleMetaDataProvider
|
|||||||
qInstance.addProcess(defineProcessScreenThenSleep());
|
qInstance.addProcess(defineProcessScreenThenSleep());
|
||||||
qInstance.addProcess(defineProcessSimpleThrow());
|
qInstance.addProcess(defineProcessSimpleThrow());
|
||||||
|
|
||||||
|
defineApps(qInstance);
|
||||||
|
|
||||||
return (qInstance);
|
return (qInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private static void defineApps(QInstance qInstance)
|
||||||
|
{
|
||||||
|
qInstance.addApp(new QAppMetaData()
|
||||||
|
.withName(APP_NAME_GREETINGS)
|
||||||
|
.withChild(qInstance.getProcess(PROCESS_NAME_GREET))
|
||||||
|
.withChild(qInstance.getProcess(PROCESS_NAME_GREET_INTERACTIVE)));
|
||||||
|
|
||||||
|
qInstance.addApp(new QAppMetaData()
|
||||||
|
.withName(APP_NAME_PEOPLE)
|
||||||
|
.withChild(qInstance.getTable(TABLE_NAME_PERSON))
|
||||||
|
.withChild(qInstance.getTable(TABLE_NAME_CITY))
|
||||||
|
.withChild(qInstance.getApp(APP_NAME_GREETINGS)));
|
||||||
|
|
||||||
|
qInstance.addApp(new QAppMetaData()
|
||||||
|
.withName(APP_NAME_MISCELLANEOUS)
|
||||||
|
.withChild(qInstance.getTable(TABLE_NAME_CARRIER))
|
||||||
|
.withChild(qInstance.getProcess(PROCESS_NAME_SIMPLE_SLEEP))
|
||||||
|
.withChild(qInstance.getProcess(PROCESS_NAME_SLEEP_INTERACTIVE))
|
||||||
|
.withChild(qInstance.getProcess(PROCESS_NAME_SIMPLE_THROW)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -166,7 +202,7 @@ public class SampleMetaDataProvider
|
|||||||
public static QTableMetaData defineTableCarrier()
|
public static QTableMetaData defineTableCarrier()
|
||||||
{
|
{
|
||||||
QTableMetaData table = new QTableMetaData();
|
QTableMetaData table = new QTableMetaData();
|
||||||
table.setName("carrier");
|
table.setName(TABLE_NAME_CARRIER);
|
||||||
table.setBackendName(RDBMS_BACKEND_NAME);
|
table.setBackendName(RDBMS_BACKEND_NAME);
|
||||||
table.setPrimaryKeyField("id");
|
table.setPrimaryKeyField("id");
|
||||||
|
|
||||||
@ -194,7 +230,7 @@ public class SampleMetaDataProvider
|
|||||||
public static QTableMetaData defineTablePerson()
|
public static QTableMetaData defineTablePerson()
|
||||||
{
|
{
|
||||||
return new QTableMetaData()
|
return new QTableMetaData()
|
||||||
.withName("person")
|
.withName(TABLE_NAME_PERSON)
|
||||||
.withLabel("Person")
|
.withLabel("Person")
|
||||||
.withBackendName(RDBMS_BACKEND_NAME)
|
.withBackendName(RDBMS_BACKEND_NAME)
|
||||||
.withPrimaryKeyField("id")
|
.withPrimaryKeyField("id")
|
||||||
@ -215,7 +251,7 @@ public class SampleMetaDataProvider
|
|||||||
public static QTableMetaData defineTableCityFile()
|
public static QTableMetaData defineTableCityFile()
|
||||||
{
|
{
|
||||||
return new QTableMetaData()
|
return new QTableMetaData()
|
||||||
.withName("city")
|
.withName(TABLE_NAME_CITY)
|
||||||
.withLabel("Cities")
|
.withLabel("Cities")
|
||||||
.withIsHidden(true)
|
.withIsHidden(true)
|
||||||
.withBackendName(FILESYSTEM_BACKEND_NAME)
|
.withBackendName(FILESYSTEM_BACKEND_NAME)
|
||||||
@ -240,7 +276,7 @@ public class SampleMetaDataProvider
|
|||||||
return new QProcessMetaData()
|
return new QProcessMetaData()
|
||||||
.withName(PROCESS_NAME_GREET)
|
.withName(PROCESS_NAME_GREET)
|
||||||
.withLabel("Greet People")
|
.withLabel("Greet People")
|
||||||
.withTableName("person")
|
.withTableName(TABLE_NAME_PERSON)
|
||||||
.withIsHidden(true)
|
.withIsHidden(true)
|
||||||
.addStep(new QBackendStepMetaData()
|
.addStep(new QBackendStepMetaData()
|
||||||
.withName("prepare")
|
.withName("prepare")
|
||||||
@ -249,14 +285,14 @@ public class SampleMetaDataProvider
|
|||||||
.withCodeType(QCodeType.JAVA)
|
.withCodeType(QCodeType.JAVA)
|
||||||
.withCodeUsage(QCodeUsage.BACKEND_STEP)) // todo - needed, or implied in this context?
|
.withCodeUsage(QCodeUsage.BACKEND_STEP)) // todo - needed, or implied in this context?
|
||||||
.withInputData(new QFunctionInputMetaData()
|
.withInputData(new QFunctionInputMetaData()
|
||||||
.withRecordListMetaData(new QRecordListMetaData().withTableName("person"))
|
.withRecordListMetaData(new QRecordListMetaData().withTableName(TABLE_NAME_PERSON))
|
||||||
.withFieldList(List.of(
|
.withFieldList(List.of(
|
||||||
new QFieldMetaData("greetingPrefix", QFieldType.STRING),
|
new QFieldMetaData("greetingPrefix", QFieldType.STRING),
|
||||||
new QFieldMetaData("greetingSuffix", QFieldType.STRING)
|
new QFieldMetaData("greetingSuffix", QFieldType.STRING)
|
||||||
)))
|
)))
|
||||||
.withOutputMetaData(new QFunctionOutputMetaData()
|
.withOutputMetaData(new QFunctionOutputMetaData()
|
||||||
.withRecordListMetaData(new QRecordListMetaData()
|
.withRecordListMetaData(new QRecordListMetaData()
|
||||||
.withTableName("person")
|
.withTableName(TABLE_NAME_PERSON)
|
||||||
.addField(new QFieldMetaData("fullGreeting", QFieldType.STRING))
|
.addField(new QFieldMetaData("fullGreeting", QFieldType.STRING))
|
||||||
)
|
)
|
||||||
.withFieldList(List.of(new QFieldMetaData("outputMessage", QFieldType.STRING))))
|
.withFieldList(List.of(new QFieldMetaData("outputMessage", QFieldType.STRING))))
|
||||||
@ -272,9 +308,9 @@ public class SampleMetaDataProvider
|
|||||||
{
|
{
|
||||||
return new QProcessMetaData()
|
return new QProcessMetaData()
|
||||||
.withName(PROCESS_NAME_GREET_INTERACTIVE)
|
.withName(PROCESS_NAME_GREET_INTERACTIVE)
|
||||||
.withTableName("person")
|
.withTableName(TABLE_NAME_PERSON)
|
||||||
|
|
||||||
.addStep(LoadInitialRecordsStep.defineMetaData("person"))
|
.addStep(LoadInitialRecordsStep.defineMetaData(TABLE_NAME_PERSON))
|
||||||
|
|
||||||
.addStep(new QFrontendStepMetaData()
|
.addStep(new QFrontendStepMetaData()
|
||||||
.withName("setup")
|
.withName("setup")
|
||||||
@ -289,14 +325,14 @@ public class SampleMetaDataProvider
|
|||||||
.withCodeType(QCodeType.JAVA)
|
.withCodeType(QCodeType.JAVA)
|
||||||
.withCodeUsage(QCodeUsage.BACKEND_STEP)) // todo - needed, or implied in this context?
|
.withCodeUsage(QCodeUsage.BACKEND_STEP)) // todo - needed, or implied in this context?
|
||||||
.withInputData(new QFunctionInputMetaData()
|
.withInputData(new QFunctionInputMetaData()
|
||||||
.withRecordListMetaData(new QRecordListMetaData().withTableName("person"))
|
.withRecordListMetaData(new QRecordListMetaData().withTableName(TABLE_NAME_PERSON))
|
||||||
.withFieldList(List.of(
|
.withFieldList(List.of(
|
||||||
new QFieldMetaData("greetingPrefix", QFieldType.STRING),
|
new QFieldMetaData("greetingPrefix", QFieldType.STRING),
|
||||||
new QFieldMetaData("greetingSuffix", QFieldType.STRING)
|
new QFieldMetaData("greetingSuffix", QFieldType.STRING)
|
||||||
)))
|
)))
|
||||||
.withOutputMetaData(new QFunctionOutputMetaData()
|
.withOutputMetaData(new QFunctionOutputMetaData()
|
||||||
.withRecordListMetaData(new QRecordListMetaData()
|
.withRecordListMetaData(new QRecordListMetaData()
|
||||||
.withTableName("person")
|
.withTableName(TABLE_NAME_PERSON)
|
||||||
.addField(new QFieldMetaData("fullGreeting", QFieldType.STRING))
|
.addField(new QFieldMetaData("fullGreeting", QFieldType.STRING))
|
||||||
)
|
)
|
||||||
.withFieldList(List.of(new QFieldMetaData("outputMessage", QFieldType.STRING))))
|
.withFieldList(List.of(new QFieldMetaData("outputMessage", QFieldType.STRING))))
|
||||||
|
Reference in New Issue
Block a user