diff --git a/adapters-api/src/main/java/io/nosqlbench/engine/api/activityconfig/ParsedStmtOp.java b/adapters-api/src/main/java/io/nosqlbench/engine/api/activityconfig/ParsedStmtOp.java
index 469cb92ef..e07f283b2 100644
--- a/adapters-api/src/main/java/io/nosqlbench/engine/api/activityconfig/ParsedStmtOp.java
+++ b/adapters-api/src/main/java/io/nosqlbench/engine/api/activityconfig/ParsedStmtOp.java
@@ -20,7 +20,7 @@ import io.nosqlbench.engine.api.activityconfig.yaml.OpTemplate;
import io.nosqlbench.nb.api.config.params.Element;
import io.nosqlbench.nb.api.config.params.NBParams;
import io.nosqlbench.virtdata.core.templates.BindPoint;
-import io.nosqlbench.virtdata.core.templates.ParsedTemplate;
+import io.nosqlbench.virtdata.core.templates.ParsedStringTemplate;
import java.util.List;
import java.util.Map;
@@ -30,7 +30,7 @@ import java.util.function.Function;
public class ParsedStmtOp {
private final OpTemplate optpl;
- private final ParsedTemplate parsed;
+ private final ParsedStringTemplate parsed;
/**
* Construct a new ParsedStatement from the provided stmtDef and anchor token.
@@ -40,7 +40,7 @@ public class ParsedStmtOp {
public ParsedStmtOp(OpTemplate optpl) {
this.optpl = optpl;
String transformed = getStmt();
- parsed = new ParsedTemplate(transformed, optpl.getBindings());
+ parsed = new ParsedStringTemplate(transformed, optpl.getBindings());
}
public ParsedStmtOp orError() {
diff --git a/adapters-api/src/main/java/io/nosqlbench/engine/api/activityconfig/yaml/OpTemplate.java b/adapters-api/src/main/java/io/nosqlbench/engine/api/activityconfig/yaml/OpTemplate.java
index 6b637749a..3e45ae73d 100644
--- a/adapters-api/src/main/java/io/nosqlbench/engine/api/activityconfig/yaml/OpTemplate.java
+++ b/adapters-api/src/main/java/io/nosqlbench/engine/api/activityconfig/yaml/OpTemplate.java
@@ -23,7 +23,7 @@ import io.nosqlbench.nb.api.config.params.Element;
import io.nosqlbench.nb.api.config.params.NBParams;
import io.nosqlbench.nb.api.config.standard.NBTypeConverter;
import io.nosqlbench.nb.api.errors.OpConfigError;
-import io.nosqlbench.virtdata.core.templates.ParsedTemplate;
+import io.nosqlbench.virtdata.core.templates.ParsedStringTemplate;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -271,9 +271,9 @@ public abstract class OpTemplate implements Tagged {
* Parse the statement for anchors and return a richer view of the StmtDef which
* is simpler to use for most statement configuration needs.
*
- * @return an optional {@link ParsedTemplate}
+ * @return an optional {@link ParsedStringTemplate}
*/
- public Optional getParsed(Function... rewriters) {
+ public Optional getParsed(Function... rewriters) {
Optional os = getStmt();
return os.map(s -> {
String result = s;
@@ -281,11 +281,11 @@ public abstract class OpTemplate implements Tagged {
result = rewriter.apply(result);
}
return result;
- }).map(s -> new ParsedTemplate(s,getBindings()));
+ }).map(s -> new ParsedStringTemplate(s,getBindings()));
}
- public Optional getParsed() {
- return getStmt().map(s -> new ParsedTemplate(s, getBindings()));
+ public Optional getParsed() {
+ return getStmt().map(s -> new ParsedStringTemplate(s, getBindings()));
}
public abstract Optional
+ *
*
* Op Template Parsing
*
- * - All op templates are parsed into an internal normalized structure which contains:
+ *
- Rule #1: All op templates are parsed into an internal normalized structure which contains:
*
- * - A map of op payload fields, which can be either of:
+ *
- A map of op fields, which can consist of:
*
* - static field values
- * - dynamic field values
+ * - dynamic field values, the actual value of which can only be known for a given cycle
*
- * -
- * Further, when the type of an op template is specified as a string, it is auto de-sugared into a map of a single
- * op payload field named 'stmt'.
*
- * - op params
- * - When neither 'op' nor 'params' is specified, all root-level op fields are put into the op payload.
- * - When either 'op' or 'params' is specified, all other root-level fields are automatically put into the other.
- * - When both 'op' and 'params' is specified, any other root-level fields causes an error to be thrown.
- *
- *
+* Access to auxiliary configuration values like activity parameters. These can back-fill
+ * when values aren't present in the direct static or dynamic op fields.
*
*
+ * Rule #2: When asking for a dynamic parameter, static parameters may be automatically promoted to functional form as a back-fill.
+ * Rule #3: When asking for static parameters, config parameters may automatically be promoted as a back-fill.
*
+ * The net effect of these rules is that the NoSQLBench driver developer may safely use functional forms to access data
+ * in the op template, or may decide that certain op fields must only be provided in a static way per operation.
*
*
* Distinguishing Op Payload from Op Config
@@ -106,27 +115,28 @@ import java.util.function.LongFunction;
*
* All of these are considered valid constructions, and all of them may actually achieve the same result.
* This looks like an undesirable problem, but it serves to simplify things for users in one specific way: It allows
- * them to be a bit ambiguous, within guidelines, and still have a valid workload definition.
+ * them to be a vague, within guidelines, and still have a valid workload definition.
* The NoSQLBench runtime does a non-trivial amount of processing on the op template to
* ensure that it can conform to an unambiguous normalized internal structure on your behalf.
* This is needed because of how awful YAML is as a user configuration language in spite of its
- * ubiquity in practice.
+ * ubiquity in practice. The basic design guideline for these forms is that the op template must
+ * mean what a reasonable user would assume without looking at any documentation.
*
*
* Design Invariants
*
-
- *
- * The above rules imply invariants, which are made explicit here. Most of these are provided for automatically by {@link ParsedOp}.
+ * The above rules imply invariants, which are made explicit here. {@link ParsedOp}.
*
*
*
* - You may not use an op field name or parameter name for more than one purpose.
*
- * - Treat all parameters supported by a drier adapter and it's op fields as a globally shared namespace, even if it is not.
+ *
- Treat all parameters supported by a driver adapter and it's op fields as a globally shared namespace, even if it is not.
* This avoids creating any confusion about what a parameter can be used for and how to use it for the right thing in the right place.
* For example, you may not use the parameter name `socket` in an op template to mean one thing and then use it
- * at the driver adapter level to mean something different.
+ * at the driver adapter level to mean something different. However, if the meaning is congruent, a driver developer
+ * may choose to support some cross-cutting parameters at the activity level. These allowances are explicit,
+ * however, as each driver dictates what it will allow as activity parameters.
*
*
*
@@ -135,7 +145,8 @@ import java.util.function.LongFunction;
*
* - IF a name is valid as an op field, it must also be valid as such when specified in op params.
* - If a name is valid as an op field, it must also be valid as such when specified in activity params, within the scope of {@link ParsedOp}
- * - When an op field is found via op params or activity params, it may be dynamic.
+ * - When an op field is found via op params or activity params, it may NOT be dynamic. If dynamic values are intended to be provided
+ * at a common layer in the workload, then bindings support this already.
*
*
*
@@ -160,6 +171,9 @@ import java.util.function.LongFunction;
* the local op payload field takes precedence.
*
* - This is an extension of the param override rules which say that the closest (most local) value to an operation is the one that takes precedence.
+ * - In practice, there will be no conflicts between direct static and dynamic fields, but there will be possibly between
+ * static or dynamic fields and parameters and activity params. If a user wants to promote an activity param as an override to existing op fields,
+ * template variables allow for this to happen gracefully. Otherwise, the order of precedence is 1) op fields 2) op params 3) activity params.
*
*
*
@@ -241,7 +255,7 @@ import java.util.function.LongFunction;
* }
*
* This example combines the previous ones with structure and dynamic values. Both field1 and field2 are dynamic,
- * since each contains some dynamic value or template within. When field1 is accessed within a cycle, that cycles value
+ * since each contains some dynamic value or template within. When field1 is accessed within a cycle, that cycle's value
* will be used as the seed to generate equivalent structures with all the literal and dynamic elements inserted as
* the template implies. As before, direct binding references like {@code {binding4}} will be inserted into the
* structure with whatever type the binding definition produces, so if you want strings in them, ensure that you
@@ -366,6 +380,10 @@ public class ParsedOp implements LongFunction