From c5f33248dc15a78734b9c47bcb59e9dca6e89b0c Mon Sep 17 00:00:00 2001 From: Jonathan Shook Date: Tue, 8 Sep 2020 17:47:23 -0500 Subject: [PATCH] improve javadoc for command template --- .../api/activityimpl/motor/ParamsParser.java | 9 ++ .../api/templating/CommandTemplate.java | 110 ++++++++++++++---- 2 files changed, 95 insertions(+), 24 deletions(-) diff --git a/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/motor/ParamsParser.java b/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/motor/ParamsParser.java index 1462a2b3a..06fb16af4 100644 --- a/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/motor/ParamsParser.java +++ b/engine-api/src/main/java/io/nosqlbench/engine/api/activityimpl/motor/ParamsParser.java @@ -77,6 +77,15 @@ public class ParamsParser { private final static Logger logger = LoggerFactory.getLogger(ParamsParser.class); + /** + * Parse a string input as a loose-form param=value list, and be reasonable about formatting + * conventions that most users would follow in the absence of detailed rules. + * See {@link ParamsParser} for more details on how this works. + * + * @param input The string form containing the parameter names and values to be extracted. + * @param canonicalize Whether or not to replace synonyms with modern forms and to warn when old forms are used + * @return A map of extracted keys and values + */ public static Map parse(String input, boolean canonicalize) { ParseState s = ParseState.expectingName; diff --git a/engine-api/src/main/java/io/nosqlbench/engine/api/templating/CommandTemplate.java b/engine-api/src/main/java/io/nosqlbench/engine/api/templating/CommandTemplate.java index d95582d3f..9c335f404 100644 --- a/engine-api/src/main/java/io/nosqlbench/engine/api/templating/CommandTemplate.java +++ b/engine-api/src/main/java/io/nosqlbench/engine/api/templating/CommandTemplate.java @@ -1,7 +1,6 @@ package io.nosqlbench.engine.api.templating; import io.nosqlbench.engine.api.activityconfig.yaml.OpTemplate; -import io.nosqlbench.engine.api.activityconfig.yaml.StmtDef; import io.nosqlbench.engine.api.activityimpl.motor.ParamsParser; import io.nosqlbench.virtdata.core.bindings.BindingsTemplate; import io.nosqlbench.virtdata.core.templates.ParsedTemplate; @@ -14,15 +13,19 @@ import java.util.*; import java.util.function.Function; /** - * Use the {@link StmtDef} template form as a property template for parameterized commands. This is a general purpose - * template which uses a map of named parameters. The {@code command} property designates the verb component of the - * command. - *

- * To be valid for use with this template type, the template specifier (the stmt String) must either start with command= - * or have a single word at the start. In either case, the command will be parsed as if it started with a command=... - *

- * The semantics of command are meant to be generalized. For example, with HTTP, command might mean the HTTP method like - * GET or PUT that is used. For web driver, it may be a webdriver command as known by the SIDE file format. + * This is a general purpose template which uses a map of named parameters. + * The result is a template which is comprised of a map of names and values, which can + * be used to create a cycle-specific map of values that can describe a literal operation + * for some native driver. How this map is used is context dependent. + * + * Generally speaking, the properties in this map are taken as parameters or field values, + * or a command verb. How the keys in the resulting map are used to construct an operation + * for execution is entirely dependent on how a developer wants to map these fields to + * a native driver's API. + * + * A CommandTemplate can be crated directly, or from an OpTemplate. Additional map parsers + * may be provided when needed for specialized forms of syntax or variations which should also + * be supported. See the constructor docs for details on these variations. */ public class CommandTemplate { @@ -32,43 +35,86 @@ public class CommandTemplate { private final Map statics = new HashMap<>(); private final Map dynamics = new HashMap<>(); - public CommandTemplate(OpTemplate stmt) { - this(stmt.getName(), stmt.getStmt(), stmt.getParamsAsValueType(String.class), stmt.getBindings(), List.of()); + /** + * Create a CommandTemplate directly from an OpTemplate. + * + * In this form, if {@link OpTemplate#getStmt()} + * is non-null, then it taken as a line-oriented value and parsed according to default {@link ParamsParser} behavior. + * + * Additionally, any op params provided are considered as entries to add to the command template's map. + * + * @param optpl An OpTemplate + */ + public CommandTemplate(OpTemplate optpl) { + this(optpl.getName(), optpl.getStmt(), optpl.getParamsAsValueType(String.class), optpl.getBindings(), List.of()); } - public CommandTemplate(OpTemplate stmt, List>> parsers) { - this(stmt.getName(), stmt.getStmt(), stmt.getParamsAsValueType(String.class), stmt.getBindings(), parsers); + /** + * Create a CommandTemplate directly from an OpTemplate, as in {@link #CommandTemplate(OpTemplate)}, + * with added support for parsing the oneline form with the provided parsers. + * + * In this form, if {@link OpTemplate#getStmt()} + * is non-null, then it taken as a line-oriented value and parsed according to default {@link ParamsParser} behavior. + * However, the provided parsers (if any) are used first in order to match alternate forms of syntax. + * + * See {@link CommandTemplate#CommandTemplate(String, String, Map, Map, List)} for full details on the provided + * parsers. + * + * @param optpl An OpTemplate + * @param parsers A list of parser functions + */ + public CommandTemplate(OpTemplate optpl, List>> parsers) { + this(optpl.getName(), optpl.getStmt(), optpl.getParamsAsValueType(String.class), optpl.getBindings(), parsers); } /** * Create a command template from a set of optional properties. * - * @param name The name of the command template - * @param oneline A oneline version of the parameters. Passed as 'stmt' in the yaml format. - * @param params A set of named parameters and values in name:value form. - * @param bindings A set of named bindings in name:recipe form. + *

The parsers provided should honor these expectations: + *

+ * + * If none of the provided parsers (if any) return a map of values for the one-line format, then the default + * behavior of {@link ParamsParser} is used. + *

+ * + * @param name The name of the command template + * @param oneline A oneline version of the parameters to be parsed by {@link ParamsParser} + * @param params A set of named parameters and values in name:value form. + * @param bindings A set of named bindings in name:recipe form. + * @param optionalParsers A set of functions which, if provided, will be used to read the oneline form. */ public CommandTemplate(String name, String oneline, Map params, Map bindings, List>> optionalParsers) { this.name = name; - Map cmd = new HashMap<>(); - // Only parse and inject the oneline form if it is defined. // The first parser to match and return a map will be the last one tried. - // If none of the suppliemental parsers work, the default params parser is used + // If none of the supplemental parsers work, the default params parser is used if (oneline != null) { - List>> parserlist = new ArrayList<>(optionalParsers); - parserlist.add(s -> ParamsParser.parse(s,false)); + List>> parserlist = new ArrayList<>(optionalParsers); + parserlist.add(s -> ParamsParser.parse(s, false)); + boolean didParse = false; for (Function> parser : parserlist) { Map parsed = parser.apply(oneline); - if (parsed!=null) { + if (parsed != null) { logger.debug("parsed request: " + parsed.toString()); cmd.putAll(parsed); + didParse = true; break; } } + if (!didParse) { + throw new RuntimeException("A oneline form was provided for the command template, but none of the " + + "provided" + + " parsers were able to parse it, not even ParamsParser.parse(...)"); + } } // Always add the named params, but warn if they overwrite any oneline named params @@ -93,6 +139,13 @@ public class CommandTemplate { } + /** + * Applyl the provided binding functions to the command template, yielding a map with concrete values + * to be used by a native command. + * + * @param cycle The cycle value which will be used by the binding functions + * @return A map of specific values + */ public Map getCommand(long cycle) { HashMap map = new HashMap<>(statics); dynamics.forEach((k, v) -> { @@ -101,14 +154,23 @@ public class CommandTemplate { return map; } + /** + * The name of the operation + */ public String getName() { return name; } + /** + * True if the command template contains all static (non-binding) values. + */ public boolean isStatic() { return this.dynamics.size() == 0; } + /** + * The set of key names known by this command template. + */ public Set getPropertyNames() { return this.statics.keySet(); }