/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.jena.query;

import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.apache.jena.atlas.lib.Pair;
import org.apache.jena.datatypes.RDFDatatype;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
import org.apache.jena.iri.IRI;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.shared.PrefixMapping;
import org.apache.jena.shared.impl.PrefixMappingImpl;
import org.apache.jena.sparql.ARQException;
import org.apache.jena.sparql.serializer.SerializationContext;
import org.apache.jena.sparql.util.FmtUtils;
import org.apache.jena.sparql.util.NodeFactoryExtra;
import org.apache.jena.update.UpdateFactory;
import org.apache.jena.update.UpdateRequest;

/**
 * <p>
 * A Parameterized SPARQL String is a SPARQL query/update into which values may
 * be injected.
 * </p>
 * <h3>Injecting Values</h3>
 * <p>
 * Values may be injected in several ways:
 * </p>
 * <ul>
 * <li>By treating a variable in the SPARQL string as a parameter</li>
 * <li>Using JDBC style positional parameters</li>
 * <li>Appending values directly to the command text being built</li>
 * </ul>
 * <h4>Variable Parameters</h3>
 * <p>
 * Any variable in the command may have a value injected to it, injecting a
 * value replaces all usages of that variable in the command i.e. substitutes
 * the variable for a constant, injection is done by textual substitution.
 * </p>
 * <h4>Positional Parameters</h4>
 * <p>
 * You can use JDBC style positional parameters if you prefer, a JDBC style
 * parameter is a single {@code ?} followed by whitespace or certain punctuation
 * characters (currently {@code ; , .}). Positional parameters have a unique
 * index which reflects the order in which they appear in the string. Positional
 * parameters use a zero based index.
 * </p>
 * <h4>Buffer Usage</h3>
 * </p>
 * Additionally you may use this purely as a {@link StringBuffer} replacement
 * for creating queries since it provides a large variety of convenience methods
 * for appending things either as-is or as nodes (which causes appropriate
 * formatting to be applied).
 * </p>
 * <h3>Intended Usage</h3>
 * <p>
 * The intended usage of this is where using a {@link QuerySolutionMap} as
 * initial bindings is either inappropriate or not possible e.g.
 * </p>
 * <ul>
 * <li>Generating query/update strings in code without lots of error prone and
 * messy string concatenation</li>
 * <li>Preparing a query/update for remote execution</li>
 * <li>Where you do not want to simply say some variable should have a certain
 * value but rather wish to insert constants into the query/update in place of
 * variables</li>
 * <li>Defending against SPARQL injection when creating a query/update using
 * some external input, see SPARQL Injection notes for limitations.</li>
 * <li>Provide a more convenient way to prepend common prefixes to your
 * query</li>
 * </ul>
 * <p>
 * This class is useful for preparing both queries and updates hence the generic
 * name as it provides programmatic ways to replace variables in the query with
 * constants and to add prefix and base declarations. A {@link Query} or
 * {@link UpdateRequest} can be created using the {@link #asQuery()} and
 * {@link #asUpdate()} methods assuming the command an instance represents is
 * actually valid as a query/update.
 * </p>
 * <h3>Warnings</h3>
 * <ol>
 * <li>Note that this class does not in any way check that your command is
 * syntactically correct until such time as you try and parse it as a
 * {@link Query} or {@link UpdateRequest}.</li>
 * <li>Also note that injection is done purely based on textual replacement, it
 * does not understand or respect variable scope in any way. For example if your
 * command text contains sub queries you should ensure that variables within the
 * sub query which you don't want replaced have distinct names from those in the
 * outer query you do want replaced (or vice versa)</li>
 * </ol>
 * <h3>SPARQL Injection Notes</h3>
 * <p>
 * While this class was in part designed to prevent SPARQL injection it is by no
 * means foolproof because it works purely at the textual level. The current
 * version of the code addresses some possible attack vectors that the
 * developers have identified but we do not claim to be sufficiently devious to
 * have thought of and prevented every possible attack vector.
 * </p>
 * <p>
 * Therefore we <strong>strongly</strong> recommend that users concerned about
 * SPARQL Injection attacks perform their own validation on provided parameters
 * and test their use of this class themselves prior to its use in any security
 * conscious deployment. We also recommend that users do not use easily
 * guess-able variable names for their parameters as these can allow a chained
 * injection attack though generally speaking the code should prevent these.
 * </p>
 */
public class ParameterizedSparqlString implements PrefixMapping {

    private Model model = ModelFactory.createDefaultModel();

    private StringBuilder cmd = new StringBuilder();
    private String baseUri;
    private Map<String, Node> params = new HashMap<>();
    private Map<Integer, Node> positionalParams = new HashMap<>();
    private PrefixMapping prefixes;
    private Map<String, ValueReplacement> valuesReplacements = new HashMap<>();
    private Syntax syntax = Syntax.defaultQuerySyntax;

    /**
     * Creates a new parameterized string
     * 
     * @param command
     *            Raw Command Text
     * @param map
     *            Initial Parameters to inject
     * @param base
     *            Base URI
     * @param prefixes
     *            Prefix Mapping
     */
    public ParameterizedSparqlString(String command, QuerySolutionMap map, String base, PrefixMapping prefixes) {
        if (command != null)
            this.cmd.append(command);
        this.setParams(map);
        this.baseUri = (base != null && !base.equals("") ? base : null);
        this.prefixes = new PrefixMappingImpl();
        if (prefixes != null)
            this.prefixes.setNsPrefixes(prefixes);
    }

    /**
     * Creates a new parameterized string
     * 
     * @param command
     *            Raw Command Text
     * @param map
     *            Initial Parameters to inject
     * @param base
     *            Base URI
     */
    public ParameterizedSparqlString(String command, QuerySolutionMap map, String base) {
        this(command, map, base, null);
    }

    /**
     * Creates a new parameterized string
     * 
     * @param command
     *            Raw Command Text
     * @param map
     *            Initial Parameters to inject
     * @param prefixes
     *            Prefix Mapping
     */
    public ParameterizedSparqlString(String command, QuerySolutionMap map, PrefixMapping prefixes) {
        this(command, map, null, prefixes);
    }

    /**
     * Creates a new parameterized string
     * 
     * @param command
     *            Raw Command Text
     * @param map
     *            Initial Parameters to inject
     */
    public ParameterizedSparqlString(String command, QuerySolutionMap map) {
        this(command, map, null, null);
    }

    /**
     * Creates a new parameterized string
     * 
     * @param command
     *            Raw Command Text
     * @param base
     *            Base URI
     * @param prefixes
     *            Prefix Mapping
     */
    public ParameterizedSparqlString(String command, String base, PrefixMapping prefixes) {
        this(command, null, base, prefixes);
    }

    /**
     * Creates a new parameterized string
     * 
     * @param command
     *            Raw Command Text
     * @param prefixes
     *            Prefix Mapping
     */
    public ParameterizedSparqlString(String command, PrefixMapping prefixes) {
        this(command, null, null, prefixes);
    }

    /**
     * Creates a new parameterized string
     * 
     * @param command
     *            Raw Command Text
     * @param base
     *            Base URI
     */
    public ParameterizedSparqlString(String command, String base) {
        this(command, null, base, null);
    }

    /**
     * Creates a new parameterized string
     * 
     * @param command
     *            Raw Command Text
     */
    public ParameterizedSparqlString(String command) {
        this(command, null, null, null);
    }

    /**
     * Creates a new parameterized string
     * 
     * @param map
     *            Initial Parameters to inject
     * @param prefixes
     *            Prefix Mapping
     */
    public ParameterizedSparqlString(QuerySolutionMap map, PrefixMapping prefixes) {
        this(null, map, null, prefixes);
    }

    /**
     * Creates a new parameterized string
     * 
     * @param map
     *            Initial Parameters to inject
     */
    public ParameterizedSparqlString(QuerySolutionMap map) {
        this(null, map, null, null);
    }

    /**
     * Creates a new parameterized string
     * 
     * @param prefixes
     *            Prefix Mapping
     */
    public ParameterizedSparqlString(PrefixMapping prefixes) {
        this(null, null, null, prefixes);
    }

    /**
     * Creates a new parameterized string with an empty command text
     */
    public ParameterizedSparqlString() {
        this("", null, null, null);
    }

    /**
     * Gets the syntax used for parsing when calling {@link #asQuery()} or
     * {@link #asUpdate()}
     * 
     * 
     * @return Syntax
     */
    public Syntax getSyntax() {
        return this.syntax;
    }

    /**
     * Sets the syntax used for parsing when calling {@link #asQuery()} or
     * {@link #asUpdate()}
     * 
     * @param syntax
     *            Syntax
     */
    public void setSyntax(Syntax syntax) {
        if (syntax == null)
            return;

        this.syntax = syntax;
    }

    /**
     * Sets the command text, overwriting any existing command text. If you want
     * to append to the command text use one of the {@link #append(String)},
     * {@link #appendIri(String)}, {@link #appendLiteral(String)} or
     * {@link #appendNode(Node)} methods instead
     * 
     * @param command
     *            Command Text
     */
    public void setCommandText(String command) {
        this.cmd = new StringBuilder();
        this.cmd.append(command);
    }

    /**
     * Appends some text as-is to the existing command text, to ensure correct
     * formatting when used as a constant consider using the
     * {@link #appendLiteral(String)} or {@link #appendIri(String)} method as
     * appropriate
     * 
     * @param text
     *            Text to append
     */
    public void append(String text) {
        this.cmd.append(text);
    }

    /**
     * Appends a character as-is to the existing command text, to ensure correct
     * formatting when used as a constant consider using one of the
     * {@code appendLiteral()} methods
     * 
     * @param c
     *            Character to append
     */
    public void append(char c) {
        this.cmd.append(c);
    }

    /**
     * Appends a boolean as-is to the existing command text, to ensure correct
     * formatting when used as a constant consider using the
     * {@link #appendLiteral(boolean)} method
     * 
     * @param b
     *            Boolean to append
     */
    public void append(boolean b) {
        this.cmd.append(b);
    }

    /**
     * Appends a double as-is to the existing command text, to ensure correct
     * formatting when used as a constant consider using the
     * {@link #appendLiteral(double)} method
     * 
     * @param d
     *            Double to append
     */
    public void append(double d) {
        this.cmd.append(d);
    }

    /**
     * Appends a float as-is to the existing command text, to ensure correct
     * formatting when used as a constant consider using the
     * {@link #appendLiteral(float)} method
     * 
     * @param f
     *            Float to append
     */
    public void append(float f) {
        this.cmd.append(f);
    }

    /**
     * Appends an integer as-is to the existing command text, to ensure correct
     * formatting when used as a constant consider using the
     * {@link #appendLiteral(int)} method
     * 
     * @param i
     *            Integer to append
     */
    public void append(int i) {
        this.cmd.append(i);
    }

    /**
     * Appends a long as-is to the existing command text, to ensure correct
     * formatting when used as a constant consider using the
     * {@link #appendLiteral(long)} method
     * 
     * @param l
     *            Long to append
     */
    public void append(long l) {
        this.cmd.append(l);
    }

    /**
     * Appends an object as-is to the existing command text, to ensure correct
     * formatting when used as a constant consider converting into a more
     * specific type and using the appropriate {@code appendLiteral()},
     * {@code appendIri()} or {@code appendNode} methods
     * 
     * @param obj
     *            Object to append
     */
    public void append(Object obj) {
        this.cmd.append(obj);
    }

    /**
     * Appends a Node to the command text as a constant using appropriate
     * formatting
     * 
     * @param n
     *            Node to append
     */
    public void appendNode(Node n) {
        SerializationContext context = new SerializationContext(this.prefixes);
        context.setBaseIRI(this.baseUri);
        this.cmd.append(this.stringForNode(n, context));
    }

    /**
     * Appends a Node to the command text as a constant using appropriate
     * formatting
     * 
     * @param n
     *            Node to append
     */
    public void appendNode(RDFNode n) {
        this.appendNode(n.asNode());
    }

    /**
     * Appends a URI to the command text as a constant using appropriate
     * formatting
     * 
     * @param uri
     *            URI to append
     */
    public void appendIri(String uri) {
        this.appendNode(NodeFactory.createURI(uri));
    }

    /**
     * Appends an IRI to the command text as a constant using appropriate
     * formatting
     * 
     * @param iri
     *            IRI to append
     */
    public void appendIri(IRI iri) {
        this.appendNode(NodeFactory.createURI(iri.toString()));
    }

    /**
     * Appends a simple literal as a constant using appropriate formatting
     * 
     * @param value
     *            Lexical Value
     */
    public void appendLiteral(String value) {
        this.appendNode(NodeFactoryExtra.createLiteralNode(value, null, null));
    }

    /**
     * Appends a literal with a lexical value and language to the command text
     * as a constant using appropriate formatting
     * 
     * @param value
     *            Lexical Value
     * @param lang
     *            Language
     */
    public void appendLiteral(String value, String lang) {
        this.appendNode(NodeFactoryExtra.createLiteralNode(value, lang, null));
    }

    /**
     * Appends a Typed Literal to the command text as a constant using
     * appropriate formatting
     * 
     * @param value
     *            Lexical Value
     * @param datatype
     *            Datatype
     */
    public void appendLiteral(String value, RDFDatatype datatype) {
        this.appendNode(NodeFactoryExtra.createLiteralNode(value, null, datatype.getURI()));
    }

    /**
     * Appends a boolean to the command text as a constant using appropriate
     * formatting
     * 
     * @param b
     *            Boolean to append
     */
    public void appendLiteral(boolean b) {
        this.appendNode(this.model.createTypedLiteral(b));
    }

    /**
     * Appends an integer to the command text as a constant using appropriate
     * formatting
     * 
     * @param i
     *            Integer to append
     */
    public void appendLiteral(int i) {
        this.appendNode(NodeFactoryExtra.intToNode(i));
    }

    /**
     * Appends a long to the command text as a constant using appropriate
     * formatting
     * 
     * @param l
     *            Long to append
     */
    public void appendLiteral(long l) {
        this.appendNode(NodeFactoryExtra.intToNode(l));
    }

    /**
     * Appends a float to the command text as a constant using appropriate
     * formatting
     * 
     * @param f
     *            Float to append
     */
    public void appendLiteral(float f) {
        this.appendNode(this.model.createTypedLiteral(f));
    }

    /**
     * Appends a double to the command text as a constant using appropriate
     * formatting
     * 
     * @param d
     *            Double to append
     */
    public void appendLiteral(double d) {
        this.appendNode(this.model.createTypedLiteral(d));
    }

    /**
     * Appends a date time to the command text as a constant using appropriate
     * formatting
     * 
     * @param dt
     *            Date Time to append
     */
    public void appendLiteral(Calendar dt) {
        this.appendNode(this.model.createTypedLiteral(dt));
    }

    /**
     * Gets the basic Command Text
     * <p>
     * <strong>Note:</strong> This will not reflect any injected parameters, to
     * see the command with injected parameters invoke the {@link #toString()}
     * method
     * </p>
     * 
     * @return Command Text
     */
    public String getCommandText() {
        return this.cmd.toString();
    }

    /**
     * Sets the Base URI which will be prepended to the query/update
     * 
     * @param base
     *            Base URI
     */
    public void setBaseUri(String base) {
        this.baseUri = base;
    }

    /**
     * Gets the Base URI which will be prepended to a query
     * 
     * @return Base URI
     */
    public String getBaseUri() {
        return this.baseUri;
    }

    /**
     * Helper method which does the validation of the parameters
     * 
     * @param n
     *            Node
     */
    protected void validateParameterValue(Node n) {
        if (n.isURI()) {
            if (n.getURI().contains(">"))
                throw new ARQException("Value for the parameter contains a SPARQL injection risk");
        }
    }

    /**
     * Sets the Parameters
     * 
     * @param map
     *            Parameters
     */
    public void setParams(QuerySolutionMap map) {
        if (map != null) {
            Iterator<String> iter = map.varNames();
            while (iter.hasNext()) {
                String var = iter.next();
                this.setParam(var, map.get(var).asNode());
            }
        }
    }

    /**
     * Sets a Positional Parameter
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(int)} for the given variable
     * </p>
     * 
     * @param index
     *            Positional Index
     * @param n
     *            Node
     */
    public void setParam(int index, Node n) {
        if (index < 0)
            throw new IndexOutOfBoundsException();
        if (n != null) {
            this.validateParameterValue(n);
            this.positionalParams.put(index, n);
        } else {
            this.positionalParams.remove(index);
        }
    }

    /**
     * Sets a variable parameter
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(String)} for the given variable
     * </p>
     * 
     * @param var
     *            Variable
     * @param n
     *            Value
     * 
     */
    public void setParam(String var, Node n) {
        if (var == null)
            throw new IllegalArgumentException("var cannot be null");
        if (var.startsWith("?") || var.startsWith("$"))
            var = var.substring(1);
        if (n != null) {
            this.validateParameterValue(n);
            this.params.put(var, n);
        } else {
            this.params.remove(var);
        }
    }

    /**
     * Sets a positional parameter
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(String)} for the given variable
     * </p>
     * 
     * @param index
     *            Positional Index
     * @param n
     *            Node
     */
    public void setParam(int index, RDFNode n) {
        this.setParam(index, n.asNode());
    }

    /**
     * Sets a variable parameter
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(String)} for the given variable
     * </p>
     * 
     * @param var
     *            Variable
     * @param n
     *            Value
     */
    public void setParam(String var, RDFNode n) {
        this.setParam(var, n.asNode());
    }

    /**
     * Sets a positional parameter to an IRI
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(int)} for the given index
     * </p>
     * 
     * @param index
     *            Positional Index
     * @param iri
     *            IRI
     */
    public void setIri(int index, String iri) {
        this.setParam(index, NodeFactory.createURI(iri));
    }

    /**
     * Sets a variable parameter to an IRI
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(String)} for the given variable
     * </p>
     * 
     * @param var
     *            Variable
     * @param iri
     *            IRI
     */
    public void setIri(String var, String iri) {
        this.setParam(var, NodeFactory.createURI(iri));
    }

    /**
     * Sets a positional parameter to an IRI
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(int)} for the given index
     * </p>
     * 
     * @param index
     *            Positional Index
     * @param iri
     *            IRI
     */
    public void setIri(int index, IRI iri) {
        this.setIri(index, iri.toString());
    }

    /**
     * Sets a variable parameter to an IRI
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(String)} for the given variable
     * </p>
     * 
     * @param var
     *            Variable
     * @param iri
     *            IRI
     */
    public void setIri(String var, IRI iri) {
        this.setIri(var, iri.toString());
    }

    /**
     * Sets a positional parameter to an IRI
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(int)} for the given index
     * </p>
     * 
     * @param index
     *            Positional Index
     * @param url
     *            URL
     */
    public void setIri(int index, URL url) {
        this.setIri(index, url.toString());
    }

    /**
     * Sets a variable parameter to an IRI
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(String)} for the given variable
     * </p>
     * 
     * @param var
     *            Variable
     * @param url
     *            URL used as IRI
     * 
     */
    public void setIri(String var, URL url) {
        this.setIri(var, url.toString());
    }

    /**
     * Sets a positional parameter to a Literal
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(int)} for the given index
     * </p>
     * 
     * @param index
     *            Positional Index
     * @param lit
     *            Value
     * 
     */
    public void setLiteral(int index, Literal lit) {
        this.setParam(index, lit.asNode());
    }

    /**
     * Sets a variable parameter to a Literal
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(String)} for the given variable
     * </p>
     * 
     * @param var
     *            Variable
     * @param lit
     *            Value
     * 
     */
    public void setLiteral(String var, Literal lit) {
        this.setParam(var, lit.asNode());
    }

    /**
     * Sets a positional parameter to a literal
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(int)} for the given index
     * </p>
     * 
     * @param index
     *            Positional Index
     * @param value
     *            Lexical Value
     * 
     */
    public void setLiteral(int index, String value) {
        this.setParam(index, NodeFactoryExtra.createLiteralNode(value, null, null));
    }

    /**
     * Sets a variable parameter to a literal
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(String)} for the given variable
     * </p>
     * 
     * @param var
     *            Variable
     * @param value
     *            Lexical Value
     * 
     */
    public void setLiteral(String var, String value) {
        this.setParam(var, NodeFactoryExtra.createLiteralNode(value, null, null));
    }

    /**
     * Sets a positional parameter to a literal with a language
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(int)} for the given index
     * </p>
     * 
     * @param index
     *            Positional index
     * @param value
     *            Lexical Value
     * @param lang
     *            Language
     * 
     */
    public void setLiteral(int index, String value, String lang) {
        this.setParam(index, NodeFactoryExtra.createLiteralNode(value, lang, null));
    }

    /**
     * Sets a variable parameter to a literal with a language
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(String)} for the given variable
     * </p>
     * 
     * @param var
     *            Variable
     * @param value
     *            Lexical Value
     * @param lang
     *            Language
     * 
     */
    public void setLiteral(String var, String value, String lang) {
        this.setParam(var, NodeFactoryExtra.createLiteralNode(value, lang, null));
    }

    /**
     * Sets a positional parameter to a typed literal
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(int)} for the given index
     * </p>
     * 
     * @param index
     *            Positional Index
     * @param value
     *            Lexical Value
     * @param datatype
     *            Datatype
     * 
     */
    public void setLiteral(int index, String value, RDFDatatype datatype) {
        this.setParam(index, this.model.createTypedLiteral(value, datatype));
    }

    /**
     * Sets a variable parameter to a typed literal
     * <p>
     * Setting a parameter to null is equivalent to calling
     * {@link #clearParam(String)} for the given variable
     * </p>
     * 
     * @param var
     *            Variable
     * @param value
     *            Lexical Value
     * @param datatype
     *            Datatype
     * 
     */
    public void setLiteral(String var, String value, RDFDatatype datatype) {
        this.setParam(var, this.model.createTypedLiteral(value, datatype));
    }

    /**
     * Sets a positional parameter to a boolean literal
     * 
     * @param index
     *            Positional Index
     * @param value
     *            boolean
     */
    public void setLiteral(int index, boolean value) {
        this.setParam(index, this.model.createTypedLiteral(value));
    }

    /**
     * Sets a variable parameter to a boolean literal
     * 
     * @param var
     *            Variable
     * @param value
     *            boolean
     */
    public void setLiteral(String var, boolean value) {
        this.setParam(var, this.model.createTypedLiteral(value));
    }

    /**
     * Sets a positional parameter to an integer literal
     * 
     * @param index
     *            Positional Index
     * @param i
     *            Integer Value
     */
    public void setLiteral(int index, int i) {
        this.setParam(index, NodeFactoryExtra.intToNode(i));
    }

    /**
     * Sets a variable parameter to an integer literal
     * 
     * @param var
     *            Variable
     * @param i
     *            Integer Value
     */
    public void setLiteral(String var, int i) {
        this.setParam(var, NodeFactoryExtra.intToNode(i));
    }

    /**
     * Sets a positional parameter to an integer literal
     * 
     * @param index
     *            Positional Index
     * @param l
     *            Integer Value
     */
    public void setLiteral(int index, long l) {
        this.setParam(index, NodeFactoryExtra.intToNode(l));
    }

    /**
     * Sets a variable parameter to an integer literal
     * 
     * @param var
     *            Variable
     * @param l
     *            Integer Value
     */
    public void setLiteral(String var, long l) {
        this.setParam(var, NodeFactoryExtra.intToNode(l));
    }

    /**
     * Sets a positional parameter to a float literal
     * 
     * @param index
     *            Positional Index
     * @param f
     *            Float value
     */
    public void setLiteral(int index, float f) {
        this.setParam(index, NodeFactoryExtra.floatToNode(f));
    }

    /**
     * Sets a variable parameter to a float literal
     * 
     * @param var
     *            Variable
     * @param f
     *            Float value
     */
    public void setLiteral(String var, float f) {
        this.setParam(var, NodeFactoryExtra.floatToNode(f));
    }

    /**
     * Sets a positional parameter to a double literal
     * 
     * @param index
     *            Positional Index
     * @param d
     *            Double value
     */
    public void setLiteral(int index, double d) {
        this.setParam(index, this.model.createTypedLiteral(d));
    }

    /**
     * Sets a variable parameter to a double literal
     * 
     * @param var
     *            Variable
     * @param d
     *            Double value
     */
    public void setLiteral(String var, double d) {
        this.setParam(var, this.model.createTypedLiteral(d));
    }

    /**
     * Sets a positional parameter to a date time literal
     * 
     * @param index
     *            Positional Index
     * @param dt
     *            Date Time value
     */
    public void setLiteral(int index, Calendar dt) {
        this.setParam(index, this.model.createTypedLiteral(dt));
    }

    /**
     * Sets a variable parameter to a date time literal
     * 
     * @param var
     *            Variable
     * @param dt
     *            Date Time value
     */
    public void setLiteral(String var, Calendar dt) {
        this.setParam(var, this.model.createTypedLiteral(dt));
    }

    /**
     * Gets the current value for a variable parameter
     * 
     * @param var
     *            Variable
     * @return Current value or null if not set
     */
    public Node getParam(String var) {
        return this.params.get(var);
    }

    /**
     * Gets the current value for a positional parameter
     * 
     * @param index
     *            Positional Index
     * @return Current value or null if not set
     */
    public Node getParam(int index) {
        return this.positionalParams.get(index);
    }

    /**
     * Gets the variable names which are currently treated as variable
     * parameters (i.e. have values set for them)
     * 
     * @return Iterator of variable names
     */
    @Deprecated
    public Iterator<String> getVars() {
        return this.params.keySet().iterator();
    }

    /**
     * Gets the map of currently set variable parameters, this will be an
     * unmodifiable map
     * 
     * @return Map of variable names and values
     */
    public Map<String, Node> getVariableParameters() {
        return Collections.unmodifiableMap(this.params);
    }

    /**
     * Gets the map of currently set positional parameters, this will be an
     * unmodifiable map
     * 
     * @return Map of positional indexes and values
     */
    public Map<Integer, Node> getPositionalParameters() {
        return Collections.unmodifiableMap(this.positionalParams);
    }

    // TODO: Detecting eligible variable parameters
    // public Iterator<String> getEligibleVariableParameters() {
    //
    // }

    /**
     * Gets the eligible positional parameters i.e. detected positional
     * parameters that may be set in the command string as it currently stands
     * 
     * @return Iterator of eligible positional parameters
     */
    public Iterator<Integer> getEligiblePositionalParameters() {
        Pattern p = Pattern.compile("(\\?)[\\s;,.]");
        List<Integer> positions = new ArrayList<>();
        int index = 0;
        Matcher matcher = p.matcher(this.cmd.toString());
        while (matcher.find()) {
            positions.add(index);
            index++;
        }
        return positions.iterator();
    }

    /**
     * Clears the value for a variable or values parameter so the given variable
     * will not * have a value injected
     * 
     * @param var
     *            Variable
     */
    public void clearParam(String var) {
        this.params.remove(var);
        this.valuesReplacements.remove(var);
    }

    /**
     * Clears the value for a positional parameter
     * 
     * @param index
     *            Positional Index
     */
    public void clearParam(int index) {
        this.positionalParams.remove(index);
    }

    /**
     * Clears all values for variable, values and positional parameters
     */
    public void clearParams() {
        this.params.clear();
        this.valuesReplacements.clear();
        this.positionalParams.clear();
    }

    /**
     * Helper method which checks whether it is safe to inject to a variable
     * parameter the given value
     * 
     * @param command
     *            Current command string
     * @param var
     *            Variable
     * @param n
     *            Value to inject
     * @throws ARQException
     *             Thrown if not safe to inject, error message will describe why
     *             it is unsafe to inject
     */
    protected void validateSafeToInject(String command, String var, Node n) throws ARQException {
        // Looks for the known injection attack vectors and throws an error if
        // any are encountered

        // A ?var surrounded by " or ' where the variable is a literal is an
        // attack vector
        Pattern p = Pattern.compile("\"[?$]" + var + "\"|'[?$]" + var + "'");

        if (p.matcher(command).find() && n.isLiteral()) {
            throw new ARQException("Command string is vunerable to injection attack, variable ?" + var
                    + " appears surrounded directly by quotes and is bound to a literal which provides a SPARQL injection attack vector");
        }

        // Parse out delimiter info
        DelimiterInfo delims = this.findDelimiters(command);

        // Check each occurrence of the variable for safety
        p = Pattern.compile("([?$]" + var + ")([^\\w]|$)");
        Matcher matcher = p.matcher(command);
        while (matcher.find()) {
            MatchResult posMatch = matcher.toMatchResult();

            if (n.isLiteral()) {
                if (delims.isInsideLiteral(posMatch.start(1), posMatch.end(1))) {
                    throw new ARQException("Command string is vunerable to injection attack, variable ?" + var
                            + " appears inside of a literal and is bound to a literal which provides a SPARQL injection attack vector");
                }
            }
        }
    }

    /**
     * Helper method which checks whether it is safe to inject to a positional
     * parameter the given value
     * 
     * @param command
     *            Current command string
     * @param index
     *            Positional parameter index
     * @param position
     *            Position within the command string at which the positional
     *            parameter occurs
     * @param n
     *            Value to inject
     * @throws ARQException
     *             Thrown if not safe to inject, error message will describe why
     *             it is unsafe to inject
     */
    protected void validateSafeToInject(String command, int index, int position, Node n) throws ARQException {
        // Parse out delimiter info
        DelimiterInfo delims = this.findDelimiters(command);

        // Check each occurrence of the variable for safety
        if (n.isLiteral()) {
            if (delims.isInsideLiteral(position, position)) {
                throw new ARQException("Command string is vunerable to injection attack, a positional paramter (index "
                        + index
                        + ") appears inside of a literal and is bound to a literal which provides a SPARQL injection attack vector");
            }
        }
    }

    /**
     * Helper method which does light parsing on the command string to find the
     * position of all relevant delimiters
     * 
     * @param command
     *            Command String
     * @return DelimiterInfo
     */
    protected final DelimiterInfo findDelimiters(String command) {
        DelimiterInfo delims = new DelimiterInfo();
        delims.parseFrom(command);
        return delims;
    }

    protected final String stringForNode(Node n, SerializationContext context) {
        String str = FmtUtils.stringForNode(n, context);
        if (n.isLiteral() && str.contains("'")) {
            // Should escape ' to avoid a possible injection vulnerability
            str = str.replace("'", "\\'");
        }
        return str;
    }

    /**
     * <p>
     * This method is where the actual work happens, the original command text
     * is always preserved and we just generated a temporary command string by
     * prepending the defined Base URI and namespace prefixes at the start of
     * the command and injecting the set parameters into a copy of that base
     * command string and return the resulting command.
     * </p>
     * <p>
     * This class makes no guarantees about the validity of the returned string
     * for use as a SPARQL Query or Update, for example if a variable parameter
     * was injected which was mentioned in the SELECT variables list you'd have
     * a syntax error when you try to parse the query. If you run into issues
     * like this try using a mixture of variable and positional parameters.
     * </p>
     * 
     * @throws ARQException
     *             May be thrown if the code detects a SPARQL Injection
     *             vulnerability because of the interaction of the command
     *             string and the injected variables
     */
    @Override
    public String toString() {
        String command = this.cmd.toString();
        Pattern p;

        // Go ahead and inject Variable Parameters
        SerializationContext context = new SerializationContext(this.prefixes);
        context.setBaseIRI(this.baseUri);
        for (String var : this.params.keySet()) {
            Node n = this.params.get(var);
            if (n == null) {
                continue;
            }
            this.validateSafeToInject(command, var, n);

            p = Pattern.compile("([?$]" + var + ")([^\\w]|$)");
            command = p.matcher(command).replaceAll(Matcher.quoteReplacement(this.stringForNode(n, context)) + "$2");
        }

        // Inject Values Parameters
        command = applyValues(command, context);

        // Then inject Positional Parameters
        // To do this we need to find the ? we will replace
        p = Pattern.compile("(\\?)[\\s;,.]");
        int index = -1;
        int adj = 0;
        Matcher matcher = p.matcher(command);
        while (matcher.find()) {
            index++;
            MatchResult posMatch = matcher.toMatchResult();

            Node n = this.positionalParams.get(index);
            if (n == null)
                continue;
            this.validateSafeToInject(command, index, posMatch.start(1) + adj, n);

            String nodeStr = this.stringForNode(n, context);
            command = command.substring(0, posMatch.start() + adj) + nodeStr
                    + command.substring(posMatch.start() + adj + 1);
            // Because we are using a matcher over the string state prior to
            // starting replacements we need to
            // track the offset adjustments to make
            adj += nodeStr.length() - 1;
        }

        // Build the final command string
        StringBuilder finalCmd = new StringBuilder();

        // Add BASE declaration
        if (this.baseUri != null) {
            finalCmd.append("BASE ");
            finalCmd.append(FmtUtils.stringForURI(this.baseUri, null, null));
            finalCmd.append('\n');
        }

        // Then pre-pend prefixes

        for (String prefix : this.prefixes.getNsPrefixMap().keySet()) {
            finalCmd.append("PREFIX ");
            finalCmd.append(prefix);
            finalCmd.append(": ");
            finalCmd.append(FmtUtils.stringForURI(this.prefixes.getNsPrefixURI(prefix), null, null));
            finalCmd.append('\n');
        }

        finalCmd.append(command);
        return finalCmd.toString();
    }

    /**
     * Attempts to take the command text with parameters injected from the
     * {@link #toString()} method and parse it as a {@link Query}
     * 
     * @return Query if the command text is a valid SPARQL query
     * @exception QueryException
     *                Thrown if the command text does not parse
     */
    public Query asQuery() throws QueryException {
        return asQuery(this.syntax);
    }

    /**
     * Attempts to take the command text with parameters injected from the
     * {@link #toString()} method and parse it as a {@link Query} using the
     * given {@link Syntax} syntax
     * 
     * @return Query if the command text is a valid SPARQL query
     * @exception QueryException
     *                Thrown if the command text does not parse
     */
    public Query asQuery(Syntax syntax) {
        return QueryFactory.create(this.toString(), syntax);
    }

    /**
     * Attempts to take the command text with parameters injected from the
     * {@link #toString()} method and parse it as a {@link UpdateRequest}
     * 
     * @return Update if the command text is a valid SPARQL Update request
     *         (one/more update commands)
     */
    public UpdateRequest asUpdate() {
        return asUpdate(this.syntax);
    }

    /**
     * Attempts to take the command text with parameters injected from the
     * {@link #toString()} method and parse it as a {@link UpdateRequest} using
     * the given {@link Syntax}
     * 
     * @return Update if the command text is a valid SPARQL Update request
     *         (one/more update commands)
     */
    public UpdateRequest asUpdate(Syntax syntax) {
        return UpdateFactory.create(this.toString(), syntax);
    }

    /**
     * Makes a full copy of this parameterized string
     * 
     * @return Copy of the string
     */
    public ParameterizedSparqlString copy() {
        return this.copy(true, true, true);
    }

    /**
     * Makes a copy of the command text, base URI and prefix mapping and
     * optionally copies parameter values
     * 
     * @param copyParams
     *            Whether to copy parameters
     * @return Copy of the string
     */
    public ParameterizedSparqlString copy(boolean copyParams) {
        return this.copy(copyParams, true, true);
    }

    /**
     * Makes a copy of the command text and optionally copies other aspects
     * 
     * @param copyParams
     *            Whether to copy parameters
     * @param copyBase
     *            Whether to copy the Base URI
     * @param copyPrefixes
     *            Whether to copy the prefix mappings
     * @return Copy of the string
     */
    public ParameterizedSparqlString copy(boolean copyParams, boolean copyBase, boolean copyPrefixes) {
        ParameterizedSparqlString copy = new ParameterizedSparqlString(this.cmd.toString(), null,
                (copyBase ? this.baseUri : null), (copyPrefixes ? this.prefixes : null));
        if (copyParams) {
            Iterator<String> vars = this.getVars();
            while (vars.hasNext()) {
                String var = vars.next();
                copy.setParam(var, this.getParam(var));
            }
            for (Entry<Integer, Node> entry : this.positionalParams.entrySet()) {
                copy.setParam(entry.getKey(), entry.getValue());
            }
        }
        copy.setSyntax(copy.getSyntax());
        return copy;
    }

    @Override
    public PrefixMapping setNsPrefix(String prefix, String uri) {
        return this.prefixes.setNsPrefix(prefix, uri);
    }

    @Override
    public PrefixMapping removeNsPrefix(String prefix) {
        return this.prefixes.removeNsPrefix(prefix);
    }

    @Override
    public PrefixMapping clearNsPrefixMap() {
        return this.prefixes.clearNsPrefixMap();
    }

    @Override
    public PrefixMapping setNsPrefixes(PrefixMapping other) {
        return this.prefixes.setNsPrefixes(other);
    }

    @Override
    public PrefixMapping setNsPrefixes(Map<String, String> map) {
        return this.prefixes.setNsPrefixes(map);
    }

    @Override
    public PrefixMapping withDefaultMappings(PrefixMapping map) {
        return this.prefixes.withDefaultMappings(map);
    }

    @Override
    public String getNsPrefixURI(String prefix) {
        return this.prefixes.getNsPrefixURI(prefix);
    }

    @Override
    public String getNsURIPrefix(String uri) {
        return this.prefixes.getNsURIPrefix(uri);
    }

    @Override
    public Map<String, String> getNsPrefixMap() {
        return this.prefixes.getNsPrefixMap();
    }

    @Override
    public String expandPrefix(String prefixed) {
        return this.prefixes.expandPrefix(prefixed);
    }

    @Override
    public String shortForm(String uri) {
        return this.prefixes.shortForm(uri);
    }

    @Override
    public String qnameFor(String uri) {
        return this.prefixes.qnameFor(uri);
    }

    @Override
    public boolean hasNoMappings() {
        return this.prefixes.hasNoMappings();
    }

    @Override
    public int numPrefixes() {
        return this.prefixes.numPrefixes();
    }

    @Override
    public PrefixMapping lock() {
        return this.prefixes.lock();
    }

    @Override
    public boolean samePrefixMappingAs(PrefixMapping other) {
        return this.prefixes.samePrefixMappingAs(other);
    }

    /**
     * Represents information about delimiters in a string
     * 
     */
    private class DelimiterInfo {
        private List<Pair<Integer, String>> starts = new ArrayList<>();
        private Map<Integer, Integer> stops = new HashMap<>();

        /**
         * Parse delimiters from a string, discards any previously parsed
         * information
         * 
         * @param command
         *            Command string
         */
        public void parseFrom(String command) {
            this.starts.clear();
            this.stops.clear();

            char[] cs = command.toCharArray();
            for (int i = 0; i < cs.length; i++) {
                switch (cs[i]) {
                case '"':
                    // Start of a Literal
                    // Is it a long literal?
                    if (i < cs.length - 2 && cs[i + 1] == '"' && cs[i + 2] == '"') {
                        this.addStart(i, "\"\"\"");
                        for (int j = i + 3; j < cs.length - 2; j++) {
                            if (cs[j] == '"' && cs[j + 1] == '"' && cs[j + 2] == '"') {
                                this.addStop(i, j + 2);
                                i = j + 2;
                                break;
                            }
                        }
                    } else {
                        // Normal literal, scan till we see a " which is not
                        // preceded by a \
                        this.addStart(i, "\"");
                        for (int j = i + 1; j < cs.length; j++) {
                            if (cs[j] == '"' && cs[j - 1] != '\\') {
                                this.addStop(i, j);
                                i = j;
                                break;
                            }
                        }
                    }
                    break;
                case '<':
                    // Start of a URI
                    this.addStart(i, "<");
                    for (int j = i + 1; j < cs.length; j++) {
                        if (cs[j] == '>' && cs[j - 1] != '\\') {
                            this.addStop(i, j);
                            i = j;
                            break;
                        }
                    }
                    break;
                case '\'':
                    // Start of alternative literal form
                    // Start of a Literal
                    // Is it a long literal?
                    if (i < cs.length - 2 && cs[i + 1] == '\'' && cs[i + 2] == '\'') {
                        this.addStart(i, "'''");
                        for (int j = i + 3; j < cs.length - 2; j++) {
                            if (cs[j] == '\'' && cs[j + 1] == '\'' && cs[j + 2] == '\'') {
                                this.addStop(i, j + 2);
                                i = j + 2;
                                break;
                            }
                        }
                    } else {
                        // Normal literal, scan till we see a ' which is not
                        // preceded by a \
                        this.addStart(i, "'");
                        for (int j = i + 1; j < cs.length; j++) {
                            if (cs[j] == '\'' && cs[j - 1] != '\\') {
                                this.addStop(i, j);
                                i = j;
                                break;
                            }
                        }
                    }
                    break;
                case '#':
                    // Start of a comment
                    // Scan to next newline
                    this.addStart(i, "#");
                    for (int j = i + 1; j < cs.length; j++) {
                        if (cs[j] == '\n' || cs[j] == '\r') {
                            this.addStop(i, j);
                            i = j;
                            break;
                        }
                    }
                    this.addStop(i, cs.length - 1);
                    break;
                case '\n':
                case '\r':
                case '.':
                case ',':
                case ';':
                case '(':
                case ')':
                case '{':
                case '}':
                case '[':
                case ']':
                    // Treat various punctuation as delimiters
                    this.addStart(i, new String(new char[] { cs[i] }));
                    this.addStop(i, i);
                    break;
                }
            }
        }

        public void addStart(int index, String delim) {
            this.starts.add(new Pair<>(index, delim));
        }

        public void addStop(int start, int stop) {
            this.stops.put(start, stop);
        }

        public Pair<Integer, String> findBefore(int index) {
            Pair<Integer, String> found = null;
            for (Pair<Integer, String> pair : this.starts) {
                if (pair.getLeft() < index)
                    found = pair;
                if (pair.getLeft() >= index)
                    break;
            }
            return found;
        }

        public Pair<Integer, String> findAfter(int index) {
            for (Pair<Integer, String> pair : this.starts) {
                if (pair.getLeft() > index)
                    return pair;
            }
            return null;
        }

        public boolean isInsideLiteral(int start, int stop) {
            Pair<Integer, String> pair = this.findBefore(start);
            if (pair == null)
                return false;
            if (pair.getRight().equals("\"")) {
                Integer nearestStop = this.stops.get(pair.getLeft());
                if (nearestStop == null)
                    return true; // Inside unterminated literal
                return (nearestStop > stop); // May be inside a literal
            } else {
                // Not inside a literal
                return false;
            }
        }

        public boolean isInsideAltLiteral(int start, int stop) {
            Pair<Integer, String> pair = this.findBefore(start);
            if (pair == null)
                return false;
            if (pair.getRight().equals("'")) {
                Integer nearestStop = this.stops.get(pair.getLeft());
                if (nearestStop == null)
                    return true; // Inside unterminated literal
                return (nearestStop > stop); // May be inside a literal
            } else {
                // Not inside a literal
                return false;
            }
        }

        public boolean isBetweenLiterals(int start, int stop) {
            Pair<Integer, String> pairBefore = this.findBefore(start);
            if (pairBefore == null)
                return false;
            if (pairBefore.getRight().equals("\"")) {
                Integer stopBefore = this.stops.get(pairBefore.getLeft());
                if (stopBefore == null)
                    return false; // Inside unterminated literal

                // We occur after a literal, is there a subsequent literal?
                Pair<Integer, String> pairAfter = this.findAfter(stop);
                return pairAfter != null && pairAfter.getRight().equals("\"");
            } else {
                // Previous deliminator is not that of a literal
                return false;
            }
        }

        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            for (Pair<Integer, String> pair : this.starts) {
                builder.append("Delim ");
                builder.append(pair.getRight());
                builder.append(" - Start ");
                builder.append(pair.getLeft());
                builder.append(" - End ");
                builder.append(this.stops.get(pair.getLeft()));
                builder.append('\n');
            }
            return builder.toString();
        }

    }

    /**
     * Assign a VALUES valueName with a multiple items.<br>
     * Can be used to assign multiple values to a single variable or single
     * value to multiple variables (if using a List) in the SPARQL query.<br>
     * See setRowValues to assign multiple values to multiple variables.<br>
     * Using "valueName" with list(prop_A, obj_A) on query "VALUES (?p ?o)
     * {?valueName}" * would produce "VALUES (?p ?o) {(prop_A obj_A)}".
     *
     *
     * @param valueName
     * @param items
     */
    public void setValues(String valueName, Collection<? extends RDFNode> items) {
        items.forEach(item -> validateParameterValue(item.asNode()));

        // Ensure that a list is used for the items.
        Collection<List<? extends RDFNode>> rowItems = new ArrayList<>();
        if (items instanceof List) {
            rowItems.add((List<? extends RDFNode>) items);
        } else {
            rowItems.add(new ArrayList<>(items));
        }
        this.valuesReplacements.put(valueName, new ValueReplacement(valueName, rowItems));
    }

    /**
     * Assign a VALUES valueName with a single item.<br>
     * Using "valueName" with Literal obj_A on query "VALUES ?o {?valueName}"
     * would produce * "VALUES ?o {obj_A}".
     *
     * @param valueName
     * @param item
     */
    public void setValues(String valueName, RDFNode item) {
        setValues(valueName, Arrays.asList(item));
    }

    /**
     * ** Sets a map of VALUES valueNames and their items.<br>
     * Can be used to assign multiple values to a single variable or single
     * value to multiple variables (if using a List) in the SPARQL query.<br>
     * See setRowValues to assign multiple values to multiple variables.
     *
     * @param itemsMap
     */
    public void setValues(Map<String, Collection<? extends RDFNode>> itemsMap) {
        itemsMap.forEach(this::setValues);
    }

    /**
     * Allocate multiple lists of variables to a single VALUES valueName.<br>
     * Using "valuesName" with list(list(prop_A, obj_A), list(prop_B, obj_B)) on
     * query "VALUES (?p ?o) {?valuesName}" would produce "VALUES (?p ?o)
     * {(prop_A obj_A) * (prop_B obj_B)}".
     *
     * @param valueName
     * @param rowItems
     */
    public void setRowValues(String valueName, Collection<List<? extends RDFNode>> rowItems) {
        rowItems.forEach(collection -> collection.forEach(item -> validateParameterValue(item.asNode())));
        this.valuesReplacements.put(valueName, new ValueReplacement(valueName, rowItems));
    }

    private String applyValues(String command, SerializationContext context) {

        for (ValueReplacement valueReplacement : valuesReplacements.values()) {
            command = valueReplacement.apply(command, context);
        }
        return command;
    }

    private static final String VALUES_KEYWORD = "values";

    protected static String[] extractTargetVars(String command, String valueName) {
        String[] targetVars = new String[] {};

        int valueIndex = command.indexOf(valueName);
        if (valueIndex > -1) {
            // Truncate the command at the valueName.
            // Lowercase to search both cases of VALUES keyword.
            String subCmd = command.substring(0, valueIndex).toLowerCase();
            int valuesIndex = subCmd.lastIndexOf(VALUES_KEYWORD);
            int openBracesIndex = subCmd.lastIndexOf("{");
            int closeBracesIndex = subCmd.lastIndexOf("}");

            // Ensure that VALUES keyword is found, open braces index is located
            // after the VALUES and any close braces is located before the
            // VALUES.
            if (valuesIndex > -1 && valuesIndex < openBracesIndex && closeBracesIndex < valuesIndex) {
                String vars = command.substring(valuesIndex + VALUES_KEYWORD.length(), openBracesIndex);
                targetVars = vars.replaceAll("[(?$)]", "").trim().split(" ");
            }
        }
        return targetVars;
    }

    /**
     * Performs replacement of VALUES in query string.
     *
     */
    private class ValueReplacement {

        private final String valueName;
        private final Collection<List<? extends RDFNode>> rowItems;

        public ValueReplacement(String valueName, Collection<List<? extends RDFNode>> rowItems) {
            this.valueName = valueName;
            this.rowItems = rowItems;
        }

        public String apply(String command, SerializationContext context) {

            if (rowItems.isEmpty()) {
                return command;
            }

            String[] targetVars = extractTargetVars(command, valueName);
            if (targetVars.length == 0) {
                // VALUES keyword has not been found or there is another issue
                // so do not modify the command.
                return command;
            }

            validateValuesSafeToInject(command, targetVars);

            String target = createTarget();
            String replacement = buildReplacement(targetVars.length, context);

            return command.replaceAll(target, replacement);
        }

        private String buildReplacement(int targetVarCount, SerializationContext context) {

            StringBuilder replacement = new StringBuilder("");

            if (targetVarCount == 1) {
                for (List<? extends RDFNode> row : rowItems) {
                    for (RDFNode item : row) {
                        replacement.append("(");
                        String insert = stringForNode(item.asNode(), context);
                        replacement.append(insert);
                        replacement.append(") ");
                    }
                }
            } else {
                for (List<? extends RDFNode> row : rowItems) {
                    replacement.append("(");
                    for (RDFNode item : row) {
                        String insert = stringForNode(item.asNode(), context);
                        replacement.append(insert);
                        replacement.append(" ");
                    }
                    replacement.deleteCharAt(replacement.length() - 1);
                    replacement.append(") ");
                }
            }

            if (replacement.length() > 0) {
                replacement.deleteCharAt(replacement.length() - 1);
            }

            return replacement.toString();
        }

        /**
         * Tidy up valueName if doesn't start with a ? or $.
         *
         * @param valueName
         * @return
         */
        private String createTarget() {
            String target;

            if (valueName.startsWith("?") || valueName.startsWith("$")) {
                target = valueName;
            } else {
                target = "[?$]" + valueName;
            }
            return target;
        }

        protected void validateValuesSafeToInject(String command, String[] targetVars) {

            if (targetVars.length == 1) {
                // Single var with one or more items so all checked against the
                // same var.
                String targetVar = targetVars[0];
                for (List<? extends RDFNode> row : rowItems) {
                    for (RDFNode item : row) {
                        validateSafeToInject(command, targetVar, item.asNode());
                    }
                }
            } else {
                // Multiple var with one or more rows.
                for (int i = 0; i < targetVars.length; i++) {
                    String targetVar = targetVars[i];
                    for (List<? extends RDFNode> row : rowItems) {
                        if (targetVars.length == row.size()) {
                            RDFNode item = row.get(i);
                            validateSafeToInject(command, targetVar, item.asNode());
                        } else {
                            String rowString = row.stream().map(RDFNode::toString).collect(Collectors.joining(","));
                            throw new ARQException("Number of VALUES variables (" + String.join(", ", targetVars)
                                    + ") does not equal replacement row (" + rowString + ").");
                        }
                    }
                }
            }
        }
    }

}
