All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.nosqlbench.engine.api.templating.CommandTemplate Maven / Gradle / Ivy

Go to download

The engine API for nosqlbench; Provides the interfaces needed to build internal modules for the nosqlbench core engine

There is a newer version: 5.17.0
Show newest version
package io.nosqlbench.engine.api.templating;

import io.nosqlbench.engine.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.ParsedTemplate;
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) -> { ParsedTemplate paramTemplate = new ParsedTemplate(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"; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy