diff --git a/adapters-api/src/main/java/io/nosqlbench/adapters/api/templating/CommandTemplate.java b/adapters-api/src/main/java/io/nosqlbench/adapters/api/templating/CommandTemplate.java deleted file mode 100644 index c29fb0a2e..000000000 --- a/adapters-api/src/main/java/io/nosqlbench/adapters/api/templating/CommandTemplate.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (c) 2022-2023 nosqlbench - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.nosqlbench.adapters.api.templating; - -import io.nosqlbench.adapters.api.activityconfig.yaml.OpTemplate; -import io.nosqlbench.nb.api.config.params.ParamsParser; -import io.nosqlbench.nb.api.errors.BasicError; -import io.nosqlbench.virtdata.core.bindings.BindingsTemplate; -import io.nosqlbench.virtdata.core.templates.ParsedTemplateString; -import io.nosqlbench.virtdata.core.templates.StringBindings; -import io.nosqlbench.virtdata.core.templates.StringBindingsTemplate; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; - -import java.util.*; -import java.util.function.Function; - -/** - * 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. - */ -@Deprecated(forRemoval = true) -public class CommandTemplate { - - private final static Logger logger = LogManager.getLogger(CommandTemplate.class); - - private final String name; - private final Map statics = new HashMap<>(); - private final Map dynamics = new HashMap<>(); - - transient private final int mapsize; - - /** - * Create a CommandTemplate directly from an OpTemplate. - * - * In this form, if {@link OpTemplate#getOp()} - * 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.getOp().toString(), optpl.getParamsAsValueType(String.class), optpl.getBindings(), List.of()); - } - - /** - * 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#getOp()} - * 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().orElseThrow(), optpl.getParamsAsValueType(String.class), optpl.getBindings(), parsers); - } - - /** - * Create a command template from a set of optional properties. - * - *

The parsers provided should honor these expectations: - *

    - *
  • If the one-line format is not recognized, the parser should return null.
  • - *
  • If the one-line format is recognized, and the values provided are valid, then they should be - * returned as a {@link Map} of {@link String} to {@link String}.
  • - *
  • Otherwise the parser should throw an exception, signifying either an internal parser error or - * invalid data.
  • - *
- * - * 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 op An object 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 op, - Map params, - Map bindings, - List>> optionalParsers - ) { - - this.name = name; - Map cmd = new HashMap<>(); - - // Only parse and inject the one-line form if it is defined. - // The first parser to match and return a map will be the last one tried. - // If none of the supplemental parsers work, the default params parser is used - - String oneline; - - if (op instanceof CharSequence) { - oneline = op; - } else { - throw new BasicError("Unable to create a oneline version of the CommandTemplate with op type of " + op.getClass().getSimpleName()); - } - if (oneline != null) { - 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) { - logger.debug(() -> "parsed request: " + parsed); - 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 - params.forEach((k, v) -> { - if (cmd.containsKey(k)) { - logger.warn("command property override: '" + k + "' superseded by param form with value '" + v + "'"); - } - }); - cmd.putAll(params); - - cmd.forEach((param, value) -> { - ParsedTemplateString paramTemplate = new ParsedTemplateString(value, bindings); - if (paramTemplate.getBindPoints().size() > 0) { - BindingsTemplate paramBindings = new BindingsTemplate(paramTemplate.getBindPoints()); - StringBindings paramStringBindings = new StringBindingsTemplate(value, paramBindings).resolve(); - dynamics.put(param, paramStringBindings); - } else { - statics.put(param, value); - } - }); - this.mapsize = statics.size() + dynamics.size(); - } - - - /** - * Apply 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<>(mapsize); - map.putAll(statics); - - dynamics.forEach((k, v) -> { - map.put(k, v.bind(cycle)); - }); - 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; - } - - public boolean isStatic(String keyname) { - return this.statics.containsKey(keyname); - } - - public boolean isStaticSet(String... keynames) { - for (String keyname : keynames) { - if (!isStatic(keyname)) { - return false; - } - } - return true; - } - - public boolean isDynamicSet(String... keynames) { - for (String keyname : keynames) { - if (!isDynamic(keyname)) { - return false; - } - } - return true; - } - - public boolean isDynamic(String keyname) { - return this.dynamics.containsKey(keyname); - } - - public boolean containsKey(String keyname) { - return this.statics.containsKey(keyname) || this.dynamics.containsKey(keyname); - } - - /** - * The set of key names known by this command template. - */ - public Set getPropertyNames() { - return this.statics.keySet(); - } - - - @Override - public String toString() { - return "CommandTemplate{" + - "name='" + name + '\'' + - ", statics=" + statics + - ", dynamics=" + dynamics + - '}'; - } - - public String getStatic(String staticVar) { - return statics.get(staticVar); - } - - public String getDynamic(String dynamicVar, long input) { - return dynamics.get(dynamicVar).bind(input); - } - - public String get(String var, long input) { - if (statics.containsKey(var)) { - return statics.get(var); - } - if (dynamics.containsKey(var)) { - return dynamics.get(var).bind(input); - } - return null; - } - - public String getOr(String var, long input, String defaultVal) { - if (statics.containsKey(var)) { - return statics.get(var); - } - if (dynamics.containsKey(var)) { - return dynamics.get(var).bind(input); - } - return defaultVal; - } - - public String getStaticOr(String staticVar, String defaultVal) { - if (statics.containsKey(staticVar)) { - return statics.get(staticVar); - } - return defaultVal; - } - - public String getDynamicOr(String dynamicVar, long input, String defaultVal) { - if (dynamics.containsKey(dynamicVar)) { - return getDynamic(dynamicVar, input); - } else { - return defaultVal; - } - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - CommandTemplate that = (CommandTemplate) o; - return Objects.equals(name, that.name) && Objects.equals(statics, that.statics) && Objects.equals(dynamics, that.dynamics); - } - - @Override - public int hashCode() { - return Objects.hash(name, statics, dynamics); - } - - public boolean containsAny(String... varNames) { - for (String varName : varNames) { - if (this.containsKey(varName)) { - return true; - } - } - return false; - } - - public boolean isStaticOrUnsetSet(String... varnames) { - for (String varname : varnames) { - if (isDynamic(varname)) { - return false; - } - } - return true; - } - - /** - * This should only be used to provide a view of a field definition, never for actual use in a payload. - * @param varname The field name which you want to explain - * @return A string representation of the field name - */ - public String getFieldDescription(String varname) { - if (this.isDynamic(varname)) { - return "dynamic: " + this.dynamics.get(varname).toString(); - } else if (this.isStatic(varname)) { - return "static: " + this.getStatic(varname); - } else { - return "UNDEFINED"; - } - } -} diff --git a/devdocs/sketches/invokable_models.md b/devdocs/sketches/invokable_models.md index 2590a5fec..48f77b53e 100644 --- a/devdocs/sketches/invokable_models.md +++ b/devdocs/sketches/invokable_models.md @@ -38,7 +38,7 @@ To clarify the differences, here are some basic examples: jmxOp.execute(); kafkaSequencer.get(cycle).write(cycle); mongoResultDoc = activity.getDatabase().runCommand(queryBson, rms.getReadPreference()); - WebDriverVerbs.execute(cycle, commandTemplate, context, dryrun); + WebDriverVerbs.execute(cycle, cmdTemplate, context, dryrun); ActivityType diff --git a/engine-core/src/main/java/io/nosqlbench/engine/api/activityimpl/SimpleActivity.java b/engine-core/src/main/java/io/nosqlbench/engine/api/activityimpl/SimpleActivity.java index ca3012efd..ba87a242b 100644 --- a/engine-core/src/main/java/io/nosqlbench/engine/api/activityimpl/SimpleActivity.java +++ b/engine-core/src/main/java/io/nosqlbench/engine/api/activityimpl/SimpleActivity.java @@ -51,7 +51,6 @@ import io.nosqlbench.adapters.api.activityimpl.uniform.DriverAdapter; import io.nosqlbench.adapters.api.activityimpl.uniform.DryRunOpDispenserWrapper; import io.nosqlbench.adapters.api.activityimpl.uniform.decorators.SyntheticOpTemplateProvider; import io.nosqlbench.adapters.api.activityimpl.uniform.flowtypes.Op; -import io.nosqlbench.adapters.api.templating.CommandTemplate; import io.nosqlbench.adapters.api.templating.ParsedOp; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -416,31 +415,6 @@ public class SimpleActivity extends NBBaseComponent implements Activity { } } - /** - * Given a function that can create an op of type from a CommandTemplate, generate - * an indexed sequence of ready to call operations. - *

- * This method works almost exactly like the , - * except that it uses the {@link CommandTemplate} semantics, which are more general and allow - * for map-based specification of operations with bindings in each field. - *

- * It is recommended to use the CommandTemplate form - * than the - * - * @param - * @param opinit - * @param strict - * @return - */ - protected OpSequence> createOpSequenceFromCommands( - Function> opinit, - boolean strict - ) { - Function f = CommandTemplate::new; - Function> opTemplateOFunction = f.andThen(opinit); - - return createOpSequence(opTemplateOFunction, strict, Optional.empty()); - } protected OpSequence> createOpSourceFromParsedOps( Map adapterCache, @@ -502,27 +476,7 @@ public class SimpleActivity extends NBBaseComponent implements Activity { } - - protected OpSequence> createOpSourceFromCommands( - Function> opinit, - NBConfiguration cfg, - List, Map>> parsers, - boolean strict - ) { - Function f = t -> new ParsedOp(t, cfg, parsers, this); - Function> opTemplateOFunction = f.andThen(opinit); - - return createOpSequence(opTemplateOFunction, strict, Optional.empty()); - } - - protected List loadParsedOps(NBConfiguration cfg, Optional defaultAdapter) { - List parsedOps = loadOpTemplates(defaultAdapter).stream().map( - ot -> new ParsedOp(ot, cfg, List.of(), this) - ).toList(); - return parsedOps; - } - - protected List loadOpTemplates(Optional defaultDriverAdapter) { + protected List loadOpTemplates(Optional> defaultDriverAdapter) { String tagfilter = activityDef.getParams().getOptionalString("tags").orElse(""); diff --git a/engine-core/src/test/java/io/nosqlbench/engine/api/templating/CommandTemplateTest.java b/engine-core/src/test/java/io/nosqlbench/engine/api/templating/CommandTemplateTest.java deleted file mode 100644 index 433e4e84a..000000000 --- a/engine-core/src/test/java/io/nosqlbench/engine/api/templating/CommandTemplateTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2022-2023 nosqlbench - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.nosqlbench.engine.api.templating; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import io.nosqlbench.adapters.api.activityconfig.OpsLoader; -import io.nosqlbench.adapters.api.activityconfig.yaml.OpTemplate; -import io.nosqlbench.adapters.api.activityconfig.yaml.OpTemplateFormat; -import io.nosqlbench.adapters.api.activityconfig.yaml.OpsDocList; -import io.nosqlbench.adapters.api.templating.CommandTemplate; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - -public class CommandTemplateTest { - private final static Logger logger = LogManager.getLogger(CommandTemplateTest.class); - - @Test - public void testCommandTemplate() { - OpsDocList opsDocs = OpsLoader.loadString("ops:\n" + - " - s1: test1=foo test2=bar", - OpTemplateFormat.yaml, Map.of(), null); - OpTemplate optpl = opsDocs.getOps(true).get(0); - CommandTemplate ct = new CommandTemplate(optpl); - assertThat(ct.isStatic()).isTrue(); - } - - @Test - public void testCommandTemplateFormat() { - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - OpsDocList stmtsDocs = OpsLoader.loadString("ops:\n" + - " - s1: test1=foo test2={bar}\n" + - " bindings:\n" + - " bar: NumberNameToString();\n", - OpTemplateFormat.yaml, Map.of(), null - ); - OpTemplate optpl = stmtsDocs.getOps(true).get(0); - CommandTemplate ct = new CommandTemplate(optpl); - String format = gson.toJson(ct); - logger.debug(format); - - } - -}