mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
Checkpoint: Added Update (edit) action; Load definition from JSON
This commit is contained in:
14
pom.xml
14
pom.xml
@ -79,7 +79,19 @@
|
|||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<!-- plugins specifically for this module -->
|
<!-- plugins specifically for this module -->
|
||||||
<!-- none at this time -->
|
<plugin>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<descriptorRefs>
|
||||||
|
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||||
|
</descriptorRefs>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<mainClass>com.kingsrook.qqq.frontend.picocli.QPicoCliImplementation</mainClass>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
<!-- Common plugins for all qqq modules -->
|
<!-- Common plugins for all qqq modules -->
|
||||||
<plugin>
|
<plugin>
|
||||||
|
@ -0,0 +1,253 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2021-2022. Kingsrook LLC <contact@kingsrook.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.kingsrook.qqq.frontend.picocli;
|
||||||
|
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.QTableMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
|
import picocli.CommandLine;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Helper class for QPicCliImplementation to build the Command
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class QCommandBuilder
|
||||||
|
{
|
||||||
|
private final QInstance qInstance;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Constructor.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public QCommandBuilder(QInstance qInstance)
|
||||||
|
{
|
||||||
|
this.qInstance = qInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
CommandLine.Model.CommandSpec buildCommandSpec(String topCommandName)
|
||||||
|
{
|
||||||
|
//////////////////////////////////
|
||||||
|
// define the top-level command //
|
||||||
|
//////////////////////////////////
|
||||||
|
CommandLine.Model.CommandSpec topCommandSpec = CommandLine.Model.CommandSpec.create();
|
||||||
|
topCommandSpec.name(topCommandName);
|
||||||
|
topCommandSpec.version(topCommandName + " v1.0"); // todo... uh?
|
||||||
|
topCommandSpec.mixinStandardHelpOptions(true); // usageHelp and versionHelp options
|
||||||
|
topCommandSpec.addOption(CommandLine.Model.OptionSpec.builder("-m", "--meta-data")
|
||||||
|
.type(boolean.class)
|
||||||
|
.description("Output the meta-data for this CLI")
|
||||||
|
.build());
|
||||||
|
|
||||||
|
/////////////////////////////////////
|
||||||
|
// add each table as a sub-command //
|
||||||
|
/////////////////////////////////////
|
||||||
|
qInstance.getTables().keySet().stream().sorted().forEach(tableName ->
|
||||||
|
{
|
||||||
|
QTableMetaData table = qInstance.getTable(tableName);
|
||||||
|
|
||||||
|
CommandLine.Model.CommandSpec tableCommand = CommandLine.Model.CommandSpec.create();
|
||||||
|
topCommandSpec.addSubcommand(table.getName(), tableCommand);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////
|
||||||
|
// add table-specific sub-commands for the table //
|
||||||
|
///////////////////////////////////////////////////
|
||||||
|
tableCommand.addSubcommand("meta-data", defineMetaDataCommand(table));
|
||||||
|
tableCommand.addSubcommand("query", defineQueryCommand(table));
|
||||||
|
tableCommand.addSubcommand("insert", defineInsertCommand(table));
|
||||||
|
tableCommand.addSubcommand("update", defineUpdateCommand(table));
|
||||||
|
tableCommand.addSubcommand("delete", defineDeleteCommand(table));
|
||||||
|
|
||||||
|
List<QProcessMetaData> processes = qInstance.getProcessesForTable(tableName);
|
||||||
|
if(CollectionUtils.nullSafeHasContents(processes))
|
||||||
|
{
|
||||||
|
tableCommand.addSubcommand("process", defineTableProcessesCommand(table, processes));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return topCommandSpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private CommandLine.Model.CommandSpec defineMetaDataCommand(QTableMetaData table)
|
||||||
|
{
|
||||||
|
return CommandLine.Model.CommandSpec.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private CommandLine.Model.CommandSpec defineQueryCommand(QTableMetaData table)
|
||||||
|
{
|
||||||
|
CommandLine.Model.CommandSpec queryCommand = CommandLine.Model.CommandSpec.create();
|
||||||
|
queryCommand.addOption(CommandLine.Model.OptionSpec.builder("-l", "--limit")
|
||||||
|
.type(int.class)
|
||||||
|
.build());
|
||||||
|
queryCommand.addOption(CommandLine.Model.OptionSpec.builder("-s", "--skip")
|
||||||
|
.type(int.class)
|
||||||
|
.build());
|
||||||
|
queryCommand.addOption(CommandLine.Model.OptionSpec.builder("-c", "--criteria")
|
||||||
|
.type(String[].class)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// todo - add the fields as explicit params?
|
||||||
|
|
||||||
|
return queryCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private CommandLine.Model.CommandSpec defineUpdateCommand(QTableMetaData table)
|
||||||
|
{
|
||||||
|
CommandLine.Model.CommandSpec updateCommand = CommandLine.Model.CommandSpec.create();
|
||||||
|
|
||||||
|
/*
|
||||||
|
updateCommand.addOption(CommandLine.Model.OptionSpec.builder("--jsonBody")
|
||||||
|
.type(String.class)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
updateCommand.addOption(CommandLine.Model.OptionSpec.builder("--jsonFile")
|
||||||
|
.type(String.class)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
updateCommand.addOption(CommandLine.Model.OptionSpec.builder("--csvFile")
|
||||||
|
.type(String.class)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
updateCommand.addOption(CommandLine.Model.OptionSpec.builder("--mapping")
|
||||||
|
.type(String.class)
|
||||||
|
.build());
|
||||||
|
*/
|
||||||
|
|
||||||
|
QFieldMetaData primaryKeyField = table.getField(table.getPrimaryKeyField());
|
||||||
|
updateCommand.addOption(CommandLine.Model.OptionSpec.builder("--primaryKey")
|
||||||
|
// type(getClassForField(primaryKeyField))
|
||||||
|
.type(String.class) // todo - mmm, better as picocli's "compound" thing, w/ the actual pkey's type?
|
||||||
|
.build());
|
||||||
|
|
||||||
|
for(QFieldMetaData field : table.getFields().values())
|
||||||
|
{
|
||||||
|
if(!field.equals(primaryKeyField))
|
||||||
|
{
|
||||||
|
updateCommand.addOption(CommandLine.Model.OptionSpec.builder("--field-" + field.getName())
|
||||||
|
.type(getClassForField(field))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return updateCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private CommandLine.Model.CommandSpec defineInsertCommand(QTableMetaData table)
|
||||||
|
{
|
||||||
|
CommandLine.Model.CommandSpec insertCommand = CommandLine.Model.CommandSpec.create();
|
||||||
|
|
||||||
|
insertCommand.addOption(CommandLine.Model.OptionSpec.builder("--jsonBody")
|
||||||
|
.type(String.class)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
insertCommand.addOption(CommandLine.Model.OptionSpec.builder("--jsonFile")
|
||||||
|
.type(String.class)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
insertCommand.addOption(CommandLine.Model.OptionSpec.builder("--csvFile")
|
||||||
|
.type(String.class)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
insertCommand.addOption(CommandLine.Model.OptionSpec.builder("--mapping")
|
||||||
|
.type(String.class)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
for(QFieldMetaData field : table.getFields().values())
|
||||||
|
{
|
||||||
|
insertCommand.addOption(CommandLine.Model.OptionSpec.builder("--field-" + field.getName())
|
||||||
|
.type(getClassForField(field))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
return insertCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private CommandLine.Model.CommandSpec defineDeleteCommand(QTableMetaData table)
|
||||||
|
{
|
||||||
|
CommandLine.Model.CommandSpec deleteCommand = CommandLine.Model.CommandSpec.create();
|
||||||
|
|
||||||
|
deleteCommand.addOption(CommandLine.Model.OptionSpec.builder("--primaryKey")
|
||||||
|
.type(String.class) // todo - mmm, better as picocli's "compound" thing, w/ the actual pkey's type?
|
||||||
|
.build());
|
||||||
|
|
||||||
|
return deleteCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private CommandLine.Model.CommandSpec defineTableProcessesCommand(QTableMetaData table, List<QProcessMetaData> processes)
|
||||||
|
{
|
||||||
|
CommandLine.Model.CommandSpec processesCommand = CommandLine.Model.CommandSpec.create();
|
||||||
|
|
||||||
|
for(QProcessMetaData process : processes)
|
||||||
|
{
|
||||||
|
CommandLine.Model.CommandSpec processCommand = CommandLine.Model.CommandSpec.create();
|
||||||
|
processesCommand.addSubcommand(process.getName(), processCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (processesCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@SuppressWarnings("checkstyle:Indentation")
|
||||||
|
private Class<?> getClassForField(QFieldMetaData field)
|
||||||
|
{
|
||||||
|
// @formatter:off // IJ can't do new-style switch correctly yet...
|
||||||
|
return switch(field.getType())
|
||||||
|
{
|
||||||
|
case STRING, TEXT, HTML, PASSWORD -> String.class;
|
||||||
|
case INTEGER -> Integer.class;
|
||||||
|
case DECIMAL -> BigDecimal.class;
|
||||||
|
case DATE -> LocalDate.class;
|
||||||
|
// case TIME -> LocalTime.class;
|
||||||
|
case DATE_TIME -> LocalDateTime.class;
|
||||||
|
};
|
||||||
|
// @formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -9,9 +9,7 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.math.BigDecimal;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -23,9 +21,11 @@ import com.kingsrook.qqq.backend.core.actions.MetaDataAction;
|
|||||||
import com.kingsrook.qqq.backend.core.actions.QueryAction;
|
import com.kingsrook.qqq.backend.core.actions.QueryAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.RunFunctionAction;
|
import com.kingsrook.qqq.backend.core.actions.RunFunctionAction;
|
||||||
import com.kingsrook.qqq.backend.core.actions.TableMetaDataAction;
|
import com.kingsrook.qqq.backend.core.actions.TableMetaDataAction;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.UpdateAction;
|
||||||
import com.kingsrook.qqq.backend.core.adapters.CsvToQRecordAdapter;
|
import com.kingsrook.qqq.backend.core.adapters.CsvToQRecordAdapter;
|
||||||
import com.kingsrook.qqq.backend.core.adapters.JsonToQFieldMappingAdapter;
|
import com.kingsrook.qqq.backend.core.adapters.JsonToQFieldMappingAdapter;
|
||||||
import com.kingsrook.qqq.backend.core.adapters.JsonToQRecordAdapter;
|
import com.kingsrook.qqq.backend.core.adapters.JsonToQRecordAdapter;
|
||||||
|
import com.kingsrook.qqq.backend.core.adapters.QInstanceAdapter;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QModuleDispatchException;
|
import com.kingsrook.qqq.backend.core.exceptions.QModuleDispatchException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.delete.DeleteRequest;
|
import com.kingsrook.qqq.backend.core.model.actions.delete.DeleteRequest;
|
||||||
@ -42,15 +42,15 @@ import com.kingsrook.qqq.backend.core.model.actions.query.QQueryFilter;
|
|||||||
import com.kingsrook.qqq.backend.core.model.actions.query.QueryRequest;
|
import com.kingsrook.qqq.backend.core.model.actions.query.QueryRequest;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.query.QueryResult;
|
import com.kingsrook.qqq.backend.core.model.actions.query.QueryResult;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.AbstractQFieldMapping;
|
import com.kingsrook.qqq.backend.core.model.actions.shared.mapping.AbstractQFieldMapping;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.update.UpdateRequest;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.update.UpdateResult;
|
||||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData;
|
|
||||||
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.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.QTableMetaData;
|
||||||
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.session.QSession;
|
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||||
import com.kingsrook.qqq.backend.core.modules.QAuthenticationModuleDispatcher;
|
import com.kingsrook.qqq.backend.core.modules.QAuthenticationModuleDispatcher;
|
||||||
import com.kingsrook.qqq.backend.core.modules.interfaces.QAuthenticationModuleInterface;
|
import com.kingsrook.qqq.backend.core.modules.interfaces.QAuthenticationModuleInterface;
|
||||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
|
||||||
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import picocli.CommandLine;
|
import picocli.CommandLine;
|
||||||
@ -81,17 +81,29 @@ public class QPicoCliImplementation
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static void main(String[] args)
|
public static void main(String[] args) throws IOException
|
||||||
{
|
{
|
||||||
QInstance qInstance = new QInstance();
|
|
||||||
|
|
||||||
// todo - parse args to look up metaData and prime instance
|
|
||||||
// todo - authentication
|
// todo - authentication
|
||||||
// qInstance.addBackend(QMetaDataProvider.getQBackend());
|
// qInstance.addBackend(QMetaDataProvider.getQBackend());
|
||||||
|
|
||||||
QPicoCliImplementation qPicoCliImplementation = new QPicoCliImplementation(qInstance);
|
// parse args to look up metaData and prime instance
|
||||||
int exitCode = qPicoCliImplementation.runCli("qapi", args);
|
if(args.length > 0 && args[0].startsWith("--qInstanceJsonFile="))
|
||||||
System.exit(exitCode);
|
{
|
||||||
|
String filePath = args[0].replaceFirst("--.*=", "");
|
||||||
|
String qInstanceJson = FileUtils.readFileToString(new File(filePath));
|
||||||
|
qInstance = new QInstanceAdapter().jsonToQInstanceIncludingBackends(qInstanceJson);
|
||||||
|
|
||||||
|
String[] subArgs = Arrays.copyOfRange(args, 1, args.length);
|
||||||
|
|
||||||
|
QPicoCliImplementation qPicoCliImplementation = new QPicoCliImplementation(qInstance);
|
||||||
|
int exitCode = qPicoCliImplementation.runCli("qapi", subArgs);
|
||||||
|
System.exit(exitCode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.err.println("To run this main class directly, you must specify: --qInstanceJsonFile=path/to/qInstance.json");
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -107,7 +119,8 @@ public class QPicoCliImplementation
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
** Driver method that uses System out & err streams.
|
||||||
|
*
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public int runCli(String name, String[] args)
|
public int runCli(String name, String[] args)
|
||||||
{
|
{
|
||||||
@ -117,6 +130,8 @@ public class QPicoCliImplementation
|
|||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
** Actual driver methods that takes streams as params.
|
||||||
|
*
|
||||||
** examples - todo, make docs complete!
|
** examples - todo, make docs complete!
|
||||||
** my-app-cli [--all] [--format=]
|
** my-app-cli [--all] [--format=]
|
||||||
** my-app-cli $table meta-data [--format=]
|
** my-app-cli $table meta-data [--format=]
|
||||||
@ -130,42 +145,7 @@ public class QPicoCliImplementation
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public int runCli(String name, String[] args, PrintStream out, PrintStream err)
|
public int runCli(String name, String[] args, PrintStream out, PrintStream err)
|
||||||
{
|
{
|
||||||
//////////////////////////////////
|
CommandSpec topCommandSpec = new QCommandBuilder(qInstance).buildCommandSpec(name);
|
||||||
// define the top-level command //
|
|
||||||
//////////////////////////////////
|
|
||||||
CommandSpec topCommandSpec = CommandSpec.create();
|
|
||||||
topCommandSpec.name(name);
|
|
||||||
topCommandSpec.version(name + " v1.0"); // todo... uh?
|
|
||||||
topCommandSpec.mixinStandardHelpOptions(true); // usageHelp and versionHelp options
|
|
||||||
topCommandSpec.addOption(OptionSpec.builder("-m", "--meta-data")
|
|
||||||
.type(boolean.class)
|
|
||||||
.description("Output the meta-data for this CLI")
|
|
||||||
.build());
|
|
||||||
|
|
||||||
/////////////////////////////////////
|
|
||||||
// add each table as a sub-command //
|
|
||||||
/////////////////////////////////////
|
|
||||||
qInstance.getTables().keySet().stream().sorted().forEach(tableName ->
|
|
||||||
{
|
|
||||||
QTableMetaData table = qInstance.getTable(tableName);
|
|
||||||
|
|
||||||
CommandSpec tableCommand = CommandSpec.create();
|
|
||||||
topCommandSpec.addSubcommand(table.getName(), tableCommand);
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////
|
|
||||||
// add table-specific sub-commands for the table //
|
|
||||||
///////////////////////////////////////////////////
|
|
||||||
tableCommand.addSubcommand("meta-data", defineMetaDataCommand(table));
|
|
||||||
tableCommand.addSubcommand("query", defineQueryCommand(table));
|
|
||||||
tableCommand.addSubcommand("insert", defineInsertCommand(table));
|
|
||||||
tableCommand.addSubcommand("delete", defineDeleteCommand(table));
|
|
||||||
|
|
||||||
List<QProcessMetaData> processes = qInstance.getProcessesForTable(tableName);
|
|
||||||
if(CollectionUtils.nullSafeHasContents(processes))
|
|
||||||
{
|
|
||||||
tableCommand.addSubcommand("process", defineTableProcessesCommand(table, processes));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
CommandLine commandLine = new CommandLine(topCommandSpec);
|
CommandLine commandLine = new CommandLine(topCommandSpec);
|
||||||
commandLine.setOut(new PrintWriter(out, true));
|
commandLine.setOut(new PrintWriter(out, true));
|
||||||
@ -215,6 +195,7 @@ public class QPicoCliImplementation
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// handle exceptions from business logic //
|
// handle exceptions from business logic //
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
ex.printStackTrace();
|
||||||
commandLine.getErr().println("Error: " + ex.getMessage());
|
commandLine.getErr().println("Error: " + ex.getMessage());
|
||||||
return (commandLine.getCommandSpec().exitCodeOnExecutionException());
|
return (commandLine.getCommandSpec().exitCodeOnExecutionException());
|
||||||
}
|
}
|
||||||
@ -238,127 +219,6 @@ public class QPicoCliImplementation
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
private CommandSpec defineMetaDataCommand(QTableMetaData table)
|
|
||||||
{
|
|
||||||
return CommandSpec.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
private CommandSpec defineQueryCommand(QTableMetaData table)
|
|
||||||
{
|
|
||||||
CommandSpec queryCommand = CommandSpec.create();
|
|
||||||
queryCommand.addOption(OptionSpec.builder("-l", "--limit")
|
|
||||||
.type(int.class)
|
|
||||||
.build());
|
|
||||||
queryCommand.addOption(OptionSpec.builder("-s", "--skip")
|
|
||||||
.type(int.class)
|
|
||||||
.build());
|
|
||||||
queryCommand.addOption(OptionSpec.builder("-c", "--criteria")
|
|
||||||
.type(String[].class)
|
|
||||||
.build());
|
|
||||||
|
|
||||||
// todo - add the fields as explicit params?
|
|
||||||
|
|
||||||
return queryCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
private CommandSpec defineInsertCommand(QTableMetaData table)
|
|
||||||
{
|
|
||||||
CommandSpec insertCommand = CommandSpec.create();
|
|
||||||
|
|
||||||
insertCommand.addOption(OptionSpec.builder("--jsonBody")
|
|
||||||
.type(String.class)
|
|
||||||
.build());
|
|
||||||
|
|
||||||
insertCommand.addOption(OptionSpec.builder("--jsonFile")
|
|
||||||
.type(String.class)
|
|
||||||
.build());
|
|
||||||
|
|
||||||
insertCommand.addOption(OptionSpec.builder("--csvFile")
|
|
||||||
.type(String.class)
|
|
||||||
.build());
|
|
||||||
|
|
||||||
insertCommand.addOption(OptionSpec.builder("--mapping")
|
|
||||||
.type(String.class)
|
|
||||||
.build());
|
|
||||||
|
|
||||||
for(QFieldMetaData field : table.getFields().values())
|
|
||||||
{
|
|
||||||
insertCommand.addOption(OptionSpec.builder("--field-" + field.getName())
|
|
||||||
.type(getClassForField(field))
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
return insertCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
private CommandSpec defineDeleteCommand(QTableMetaData table)
|
|
||||||
{
|
|
||||||
CommandSpec deleteCommand = CommandSpec.create();
|
|
||||||
|
|
||||||
deleteCommand.addOption(OptionSpec.builder("--primaryKey")
|
|
||||||
.type(String.class) // todo - mmm, better as picocli's "compound" thing, w/ the actual pkey's type?
|
|
||||||
.build());
|
|
||||||
|
|
||||||
return deleteCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
private CommandSpec defineTableProcessesCommand(QTableMetaData table, List<QProcessMetaData> processes)
|
|
||||||
{
|
|
||||||
CommandSpec processesCommand = CommandSpec.create();
|
|
||||||
|
|
||||||
for(QProcessMetaData process : processes)
|
|
||||||
{
|
|
||||||
CommandSpec processCommand = CommandSpec.create();
|
|
||||||
processesCommand.addSubcommand(process.getName(), processCommand);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (processesCommand);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
**
|
|
||||||
*******************************************************************************/
|
|
||||||
private Class<?> getClassForField(QFieldMetaData field)
|
|
||||||
{
|
|
||||||
// @formatter:off // IJ can't do new-style switch correctly yet...
|
|
||||||
return switch(field.getType())
|
|
||||||
{
|
|
||||||
case STRING, TEXT, HTML, PASSWORD -> String.class;
|
|
||||||
case INTEGER -> Integer.class;
|
|
||||||
case DECIMAL -> BigDecimal.class;
|
|
||||||
case DATE -> LocalDate.class;
|
|
||||||
// case TIME -> LocalTime.class;
|
|
||||||
case DATE_TIME -> LocalDateTime.class;
|
|
||||||
};
|
|
||||||
// @formatter:on
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -403,6 +263,10 @@ public class QPicoCliImplementation
|
|||||||
{
|
{
|
||||||
return runTableInsert(commandLine, tableName, subParseResult);
|
return runTableInsert(commandLine, tableName, subParseResult);
|
||||||
}
|
}
|
||||||
|
case "update":
|
||||||
|
{
|
||||||
|
return runTableUpdate(commandLine, tableName, subParseResult);
|
||||||
|
}
|
||||||
case "delete":
|
case "delete":
|
||||||
{
|
{
|
||||||
return runTableDelete(commandLine, tableName, subParseResult);
|
return runTableDelete(commandLine, tableName, subParseResult);
|
||||||
@ -602,6 +466,57 @@ public class QPicoCliImplementation
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
private int runTableUpdate(CommandLine commandLine, String tableName, ParseResult subParseResult) throws QException
|
||||||
|
{
|
||||||
|
UpdateRequest updateRequest = new UpdateRequest(qInstance);
|
||||||
|
updateRequest.setSession(session);
|
||||||
|
updateRequest.setTableName(tableName);
|
||||||
|
QTableMetaData table = qInstance.getTable(tableName);
|
||||||
|
|
||||||
|
List<QRecord> recordList = new ArrayList<>();
|
||||||
|
|
||||||
|
boolean anyFields = false;
|
||||||
|
|
||||||
|
String primaryKeyOption = subParseResult.matchedOptionValue("--primaryKey", "");
|
||||||
|
Serializable[] primaryKeyValues = primaryKeyOption.split(",");
|
||||||
|
for(Serializable primaryKeyValue : primaryKeyValues)
|
||||||
|
{
|
||||||
|
QRecord record = new QRecord();
|
||||||
|
|
||||||
|
recordList.add(record);
|
||||||
|
record.setValue(table.getPrimaryKeyField(), primaryKeyValue);
|
||||||
|
|
||||||
|
for(OptionSpec matchedOption : subParseResult.matchedOptions())
|
||||||
|
{
|
||||||
|
if(matchedOption.longestName().startsWith("--field-"))
|
||||||
|
{
|
||||||
|
anyFields = true;
|
||||||
|
String fieldName = matchedOption.longestName().substring(8);
|
||||||
|
record.setValue(fieldName, matchedOption.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!anyFields || recordList.isEmpty())
|
||||||
|
{
|
||||||
|
CommandLine subCommandLine = commandLine.getSubcommands().get("update");
|
||||||
|
subCommandLine.usage(commandLine.getOut());
|
||||||
|
return commandLine.getCommandSpec().exitCodeOnUsageHelp();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRequest.setRecords(recordList);
|
||||||
|
|
||||||
|
UpdateAction updateAction = new UpdateAction();
|
||||||
|
UpdateResult updateResult = updateAction.execute(updateRequest);
|
||||||
|
commandLine.getOut().println(JsonUtils.toPrettyJson(updateResult));
|
||||||
|
return commandLine.getCommandSpec().exitCodeOnSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -615,7 +530,7 @@ public class QPicoCliImplementation
|
|||||||
// get the pKeys that the user specified //
|
// get the pKeys that the user specified //
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
String primaryKeyOption = subParseResult.matchedOptionValue("--primaryKey", "");
|
String primaryKeyOption = subParseResult.matchedOptionValue("--primaryKey", "");
|
||||||
String[] primaryKeyValues = primaryKeyOption.split(",");
|
Serializable[] primaryKeyValues = primaryKeyOption.split(",");
|
||||||
deleteRequest.setPrimaryKeys(Arrays.asList(primaryKeyValues));
|
deleteRequest.setPrimaryKeys(Arrays.asList(primaryKeyValues));
|
||||||
|
|
||||||
DeleteAction deleteAction = new DeleteAction();
|
DeleteAction deleteAction = new DeleteAction();
|
||||||
|
@ -198,10 +198,11 @@ class QPicoCliImplementationTest
|
|||||||
TestOutput testOutput = testCli("person", "query", "--skip=1", "--limit=2", "--criteria", "id NOT_EQUALS 3");
|
TestOutput testOutput = testCli("person", "query", "--skip=1", "--limit=2", "--criteria", "id NOT_EQUALS 3");
|
||||||
JSONObject queryResult = JsonUtils.toJSONObject(testOutput.getOutput());
|
JSONObject queryResult = JsonUtils.toJSONObject(testOutput.getOutput());
|
||||||
assertNotNull(queryResult);
|
assertNotNull(queryResult);
|
||||||
assertEquals(2, queryResult.getJSONArray("records").length());
|
JSONArray records = queryResult.getJSONArray("records");
|
||||||
|
assertEquals(2, records.length());
|
||||||
// query for id != 3, and skipping 1, expect to get back rows 2 & 4
|
// query for id != 3, and skipping 1, expect to get back rows 2 & 4
|
||||||
assertEquals(2, queryResult.getJSONArray("records").getJSONObject(0).getInt("primaryKey"));
|
assertEquals(2, records.getJSONObject(0).getJSONObject("values").getInt("id"));
|
||||||
assertEquals(4, queryResult.getJSONArray("records").getJSONObject(1).getInt("primaryKey"));
|
assertEquals(4, records.getJSONObject(1).getJSONObject("values").getInt("id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -232,7 +233,7 @@ class QPicoCliImplementationTest
|
|||||||
JSONObject insertResult = JsonUtils.toJSONObject(testOutput.getOutput());
|
JSONObject insertResult = JsonUtils.toJSONObject(testOutput.getOutput());
|
||||||
assertNotNull(insertResult);
|
assertNotNull(insertResult);
|
||||||
assertEquals(1, insertResult.getJSONArray("records").length());
|
assertEquals(1, insertResult.getJSONArray("records").length());
|
||||||
assertEquals(6, insertResult.getJSONArray("records").getJSONObject(0).getInt("primaryKey"));
|
assertEquals(6, insertResult.getJSONArray("records").getJSONObject(0).getJSONObject("values").getInt("id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -256,7 +257,7 @@ class QPicoCliImplementationTest
|
|||||||
JSONObject insertResult = JsonUtils.toJSONObject(testOutput.getOutput());
|
JSONObject insertResult = JsonUtils.toJSONObject(testOutput.getOutput());
|
||||||
assertNotNull(insertResult);
|
assertNotNull(insertResult);
|
||||||
assertEquals(1, insertResult.getJSONArray("records").length());
|
assertEquals(1, insertResult.getJSONArray("records").length());
|
||||||
assertEquals(6, insertResult.getJSONArray("records").getJSONObject(0).getInt("primaryKey"));
|
assertEquals(6, insertResult.getJSONArray("records").getJSONObject(0).getJSONObject("values").getInt("id"));
|
||||||
assertEquals("Chester", insertResult.getJSONArray("records").getJSONObject(0).getJSONObject("values").getString("firstName"));
|
assertEquals("Chester", insertResult.getJSONArray("records").getJSONObject(0).getJSONObject("values").getString("firstName"));
|
||||||
assertEquals("Cheese", insertResult.getJSONArray("records").getJSONObject(0).getJSONObject("values").getString("lastName"));
|
assertEquals("Cheese", insertResult.getJSONArray("records").getJSONObject(0).getJSONObject("values").getString("lastName"));
|
||||||
}
|
}
|
||||||
@ -287,8 +288,8 @@ class QPicoCliImplementationTest
|
|||||||
assertNotNull(insertResult);
|
assertNotNull(insertResult);
|
||||||
JSONArray records = insertResult.getJSONArray("records");
|
JSONArray records = insertResult.getJSONArray("records");
|
||||||
assertEquals(2, records.length());
|
assertEquals(2, records.length());
|
||||||
assertEquals(6, records.getJSONObject(0).getInt("primaryKey"));
|
assertEquals(6, insertResult.getJSONArray("records").getJSONObject(0).getJSONObject("values").getInt("id"));
|
||||||
assertEquals(7, records.getJSONObject(1).getInt("primaryKey"));
|
assertEquals(7, insertResult.getJSONArray("records").getJSONObject(1).getJSONObject("values").getInt("id"));
|
||||||
assertEquals("Charlie", records.getJSONObject(0).getJSONObject("values").getString("firstName"));
|
assertEquals("Charlie", records.getJSONObject(0).getJSONObject("values").getString("firstName"));
|
||||||
assertEquals("Bear", records.getJSONObject(0).getJSONObject("values").getString("lastName"));
|
assertEquals("Bear", records.getJSONObject(0).getJSONObject("values").getString("lastName"));
|
||||||
assertEquals("Coco", records.getJSONObject(1).getJSONObject("values").getString("firstName"));
|
assertEquals("Coco", records.getJSONObject(1).getJSONObject("values").getString("firstName"));
|
||||||
@ -323,8 +324,8 @@ class QPicoCliImplementationTest
|
|||||||
assertNotNull(insertResult);
|
assertNotNull(insertResult);
|
||||||
JSONArray records = insertResult.getJSONArray("records");
|
JSONArray records = insertResult.getJSONArray("records");
|
||||||
assertEquals(2, records.length());
|
assertEquals(2, records.length());
|
||||||
assertEquals(6, records.getJSONObject(0).getInt("primaryKey"));
|
assertEquals(6, insertResult.getJSONArray("records").getJSONObject(0).getJSONObject("values").getInt("id"));
|
||||||
assertEquals(7, records.getJSONObject(1).getInt("primaryKey"));
|
assertEquals(7, insertResult.getJSONArray("records").getJSONObject(1).getJSONObject("values").getInt("id"));
|
||||||
assertEquals("Louis", records.getJSONObject(0).getJSONObject("values").getString("firstName"));
|
assertEquals("Louis", records.getJSONObject(0).getJSONObject("values").getString("firstName"));
|
||||||
assertEquals("Willikers", records.getJSONObject(0).getJSONObject("values").getString("lastName"));
|
assertEquals("Willikers", records.getJSONObject(0).getJSONObject("values").getString("lastName"));
|
||||||
assertEquals("Nestle", records.getJSONObject(1).getJSONObject("values").getString("firstName"));
|
assertEquals("Nestle", records.getJSONObject(1).getJSONObject("values").getString("firstName"));
|
||||||
@ -333,6 +334,56 @@ class QPicoCliImplementationTest
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** test running an update w/o specifying any fields, prints usage
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
public void test_tableUpdateNoFieldsPrintsUsage()
|
||||||
|
{
|
||||||
|
TestOutput testOutput = testCli("person", "update");
|
||||||
|
assertTestOutputContains(testOutput, "Usage: " + CLI_NAME + " person update");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** test running an update w/ fields as arguments
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
public void test_tableUpdateFieldArguments() throws Exception
|
||||||
|
{
|
||||||
|
assertRowValueById("person", "first_name", "Garret", 5);
|
||||||
|
TestOutput testOutput = testCli("person", "update",
|
||||||
|
"--primaryKey=5",
|
||||||
|
"--field-firstName=Lucy",
|
||||||
|
"--field-lastName=Lu");
|
||||||
|
JSONObject updateResult = JsonUtils.toJSONObject(testOutput.getOutput());
|
||||||
|
assertNotNull(updateResult);
|
||||||
|
assertEquals(1, updateResult.getJSONArray("records").length());
|
||||||
|
assertEquals(5, updateResult.getJSONArray("records").getJSONObject(0).getJSONObject("values").getInt("id"));
|
||||||
|
assertRowValueById("person", "first_name", "Lucy", 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void assertRowValueById(String tableName, String columnName, String value, Integer id) throws Exception
|
||||||
|
{
|
||||||
|
TestUtils.runTestSql("SELECT " + columnName + " FROM " + tableName + " WHERE id=" + id, (rs -> {
|
||||||
|
if(rs.next())
|
||||||
|
{
|
||||||
|
assertEquals(value, rs.getString(1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fail("Row not found");
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** test running a delete against a table
|
** test running a delete against a table
|
||||||
**
|
**
|
||||||
@ -343,9 +394,10 @@ class QPicoCliImplementationTest
|
|||||||
TestOutput testOutput = testCli("person", "delete", "--primaryKey", "2,4");
|
TestOutput testOutput = testCli("person", "delete", "--primaryKey", "2,4");
|
||||||
JSONObject deleteResult = JsonUtils.toJSONObject(testOutput.getOutput());
|
JSONObject deleteResult = JsonUtils.toJSONObject(testOutput.getOutput());
|
||||||
assertNotNull(deleteResult);
|
assertNotNull(deleteResult);
|
||||||
assertEquals(2, deleteResult.getJSONArray("records").length());
|
JSONArray records = deleteResult.getJSONArray("records");
|
||||||
assertEquals(2, deleteResult.getJSONArray("records").getJSONObject(0).getInt("primaryKey"));
|
assertEquals(2, records.length());
|
||||||
assertEquals(4, deleteResult.getJSONArray("records").getJSONObject(1).getInt("primaryKey"));
|
assertEquals(2, records.getJSONObject(0).getJSONObject("values").getInt("id"));
|
||||||
|
assertEquals(4, records.getJSONObject(1).getJSONObject("values").getInt("id"));
|
||||||
TestUtils.runTestSql("SELECT id FROM person", (rs -> {
|
TestUtils.runTestSql("SELECT id FROM person", (rs -> {
|
||||||
int rowsFound = 0;
|
int rowsFound = 0;
|
||||||
while(rs.next())
|
while(rs.next())
|
||||||
|
@ -9,13 +9,13 @@ import java.io.InputStream;
|
|||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.QAuthenticationMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QCodeReference;
|
import com.kingsrook.qqq.backend.core.model.metadata.QCodeReference;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QCodeType;
|
import com.kingsrook.qqq.backend.core.model.metadata.QCodeType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QCodeUsage;
|
import com.kingsrook.qqq.backend.core.model.metadata.QCodeUsage;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.QFieldMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QFieldType;
|
import com.kingsrook.qqq.backend.core.model.metadata.QFieldType;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QTableMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.QTableMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionInputMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.processes.QFunctionMetaData;
|
||||||
|
156
src/test/resources/personQInstance.json
Normal file
156
src/test/resources/personQInstance.json
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
{
|
||||||
|
"authentication": {
|
||||||
|
"name": "mock",
|
||||||
|
"type": "mock",
|
||||||
|
"values": null
|
||||||
|
},
|
||||||
|
"tables": {
|
||||||
|
"person": {
|
||||||
|
"name": "person",
|
||||||
|
"label": "Person",
|
||||||
|
"backendName": "default",
|
||||||
|
"primaryKeyField": "id",
|
||||||
|
"fields": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"label": null,
|
||||||
|
"backendName": null,
|
||||||
|
"type": "INTEGER",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"createDate": {
|
||||||
|
"name": "createDate",
|
||||||
|
"label": null,
|
||||||
|
"backendName": null,
|
||||||
|
"type": "DATE_TIME",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"modifyDate": {
|
||||||
|
"name": "modifyDate",
|
||||||
|
"label": null,
|
||||||
|
"backendName": null,
|
||||||
|
"type": "DATE_TIME",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"firstName": {
|
||||||
|
"name": "firstName",
|
||||||
|
"label": null,
|
||||||
|
"backendName": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"name": "lastName",
|
||||||
|
"label": null,
|
||||||
|
"backendName": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"birthDate": {
|
||||||
|
"name": "birthDate",
|
||||||
|
"label": null,
|
||||||
|
"backendName": null,
|
||||||
|
"type": "DATE",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"name": "email",
|
||||||
|
"label": null,
|
||||||
|
"backendName": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"homeState": {
|
||||||
|
"name": "homeState",
|
||||||
|
"label": null,
|
||||||
|
"backendName": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": "state"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"possibleValueSources": {
|
||||||
|
"state": {
|
||||||
|
"name": "state",
|
||||||
|
"type": "ENUM",
|
||||||
|
"enumValues": [
|
||||||
|
"IL",
|
||||||
|
"MO"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"processes": {
|
||||||
|
"greet": {
|
||||||
|
"name": "greet",
|
||||||
|
"tableName": "person",
|
||||||
|
"functionList": [
|
||||||
|
{
|
||||||
|
"name": "prepare",
|
||||||
|
"label": null,
|
||||||
|
"inputMetaData": {
|
||||||
|
"recordListMetaData": {
|
||||||
|
"tableName": "person",
|
||||||
|
"fields": null
|
||||||
|
},
|
||||||
|
"fieldList": [
|
||||||
|
{
|
||||||
|
"name": "greetingPrefix",
|
||||||
|
"label": null,
|
||||||
|
"backendName": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "greetingSuffix",
|
||||||
|
"label": null,
|
||||||
|
"backendName": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"outputMetaData": {
|
||||||
|
"recordListMetaData": {
|
||||||
|
"tableName": "person",
|
||||||
|
"fields": {
|
||||||
|
"fullGreeting": {
|
||||||
|
"name": "fullGreeting",
|
||||||
|
"label": null,
|
||||||
|
"backendName": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fieldList": [
|
||||||
|
{
|
||||||
|
"name": "outputMessage",
|
||||||
|
"label": null,
|
||||||
|
"backendName": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"name": "com.kingsrook.qqq.backend.core.interfaces.mock.MockFunctionBody",
|
||||||
|
"codeType": "JAVA",
|
||||||
|
"codeUsage": "FUNCTION"
|
||||||
|
},
|
||||||
|
"outputView": {
|
||||||
|
"messageField": "outputMessage",
|
||||||
|
"recordListView": {
|
||||||
|
"fieldNames": [
|
||||||
|
"id",
|
||||||
|
"firstName",
|
||||||
|
"lastName",
|
||||||
|
"fullGreeting"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
163
src/test/resources/personQInstanceIncludingBackend.json
Normal file
163
src/test/resources/personQInstanceIncludingBackend.json
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
{
|
||||||
|
"tables": {
|
||||||
|
"person": {
|
||||||
|
"primaryKeyField": "id",
|
||||||
|
"name": "person",
|
||||||
|
"backendName": "default",
|
||||||
|
"label": "Person",
|
||||||
|
"fields": {
|
||||||
|
"firstName": {
|
||||||
|
"name": "firstName",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"lastName": {
|
||||||
|
"name": "lastName",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"modifyDate": {
|
||||||
|
"name": "modifyDate",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "DATE_TIME",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"homeState": {
|
||||||
|
"name": "homeState",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": "state"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "INTEGER",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"birthDate": {
|
||||||
|
"name": "birthDate",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "DATE",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"name": "email",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"createDate": {
|
||||||
|
"name": "createDate",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "DATE_TIME",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"processes": {
|
||||||
|
"greet": {
|
||||||
|
"functionList": [
|
||||||
|
{
|
||||||
|
"code": {
|
||||||
|
"codeUsage": "FUNCTION",
|
||||||
|
"codeType": "JAVA",
|
||||||
|
"name": "com.kingsrook.qqq.backend.core.interfaces.mock.MockFunctionBody"
|
||||||
|
},
|
||||||
|
"inputMetaData": {
|
||||||
|
"recordListMetaData": {
|
||||||
|
"fields": null,
|
||||||
|
"tableName": "person"
|
||||||
|
},
|
||||||
|
"fieldList": [
|
||||||
|
{
|
||||||
|
"name": "greetingPrefix",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "greetingSuffix",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"outputMetaData": {
|
||||||
|
"recordListMetaData": {
|
||||||
|
"fields": {
|
||||||
|
"fullGreeting": {
|
||||||
|
"name": "fullGreeting",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tableName": "person"
|
||||||
|
},
|
||||||
|
"fieldList": [
|
||||||
|
{
|
||||||
|
"name": "outputMessage",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"outputView": {
|
||||||
|
"messageField": "outputMessage",
|
||||||
|
"recordListView": {
|
||||||
|
"fieldNames": [
|
||||||
|
"id",
|
||||||
|
"firstName",
|
||||||
|
"lastName",
|
||||||
|
"fullGreeting"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "prepare",
|
||||||
|
"label": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "greet",
|
||||||
|
"tableName": "person"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"possibleValueSources": {
|
||||||
|
"state": {
|
||||||
|
"name": "state",
|
||||||
|
"type": "ENUM",
|
||||||
|
"enumValues": [
|
||||||
|
"IL",
|
||||||
|
"MO"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"backends": {
|
||||||
|
"default": {
|
||||||
|
"values": null,
|
||||||
|
"name": "default",
|
||||||
|
"type": "mock"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"authentication": {
|
||||||
|
"values": null,
|
||||||
|
"name": "mock",
|
||||||
|
"type": "mock"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"tables": {
|
||||||
|
"series": {
|
||||||
|
"primaryKeyField": "id",
|
||||||
|
"name": "series",
|
||||||
|
"backendName": "wherenooneMysql",
|
||||||
|
"label": "Person",
|
||||||
|
"fields": {
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"abbreviation": {
|
||||||
|
"name": "abbreviation",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "STRING",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"backendName": null,
|
||||||
|
"label": null,
|
||||||
|
"type": "INTEGER",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"createDate": {
|
||||||
|
"name": "createDate",
|
||||||
|
"backendName": "create_date",
|
||||||
|
"label": "Create Date",
|
||||||
|
"type": "DATE_TIME",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
},
|
||||||
|
"modifyDate": {
|
||||||
|
"name": "modifyDate",
|
||||||
|
"backendName": "modify_date",
|
||||||
|
"label": "Modify Date",
|
||||||
|
"type": "DATE_TIME",
|
||||||
|
"possibleValueSourceName": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"processes": {
|
||||||
|
},
|
||||||
|
"possibleValueSources": {
|
||||||
|
},
|
||||||
|
"backends": {
|
||||||
|
"wherenooneMysql": {
|
||||||
|
"values": {
|
||||||
|
"vendor": "mysql",
|
||||||
|
"hostName": "localhost",
|
||||||
|
"port": "3306",
|
||||||
|
"databaseName": "wherenoone",
|
||||||
|
"username": "root",
|
||||||
|
"password": "password"
|
||||||
|
},
|
||||||
|
"name": "wherenooneMysql",
|
||||||
|
"type": "rdbms"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"authentication": {
|
||||||
|
"values": null,
|
||||||
|
"name": "mock",
|
||||||
|
"type": "mock"
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user