blob: c0ffd77329e239f6aed3d9d3c76b2c8afc3c907a [file] [log] [blame]
/*
* 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.arq.querybuilder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import org.apache.jena.arq.querybuilder.clauses.PrologClause;
import org.apache.jena.arq.querybuilder.clauses.WhereClause;
import org.apache.jena.arq.querybuilder.handlers.WhereHandler;
import org.apache.jena.arq.querybuilder.updatebuilder.CollectionQuadHolder;
import org.apache.jena.arq.querybuilder.updatebuilder.ModelQuadHolder;
import org.apache.jena.arq.querybuilder.updatebuilder.PrefixHandler;
import org.apache.jena.arq.querybuilder.updatebuilder.QBQuadHolder;
import org.apache.jena.arq.querybuilder.updatebuilder.QuadCollectionHolder;
import org.apache.jena.arq.querybuilder.updatebuilder.QuadHolder;
import org.apache.jena.arq.querybuilder.updatebuilder.SingleQuadHolder;
import org.apache.jena.arq.querybuilder.updatebuilder.WhereQuadHolder;
import org.apache.jena.graph.FrontsTriple;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
import org.apache.jena.graph.Triple;
import org.apache.jena.query.QueryParseException;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.shared.PrefixMapping;
import org.apache.jena.sparql.core.Quad;
import org.apache.jena.sparql.core.TriplePath;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.expr.Expr;
import org.apache.jena.sparql.modify.request.QuadAcc;
import org.apache.jena.sparql.modify.request.QuadDataAcc;
import org.apache.jena.sparql.modify.request.UpdateDataDelete;
import org.apache.jena.sparql.modify.request.UpdateDataInsert;
import org.apache.jena.sparql.modify.request.UpdateDeleteWhere;
import org.apache.jena.sparql.modify.request.UpdateModify;
import org.apache.jena.sparql.path.Path;
import org.apache.jena.update.Update;
import org.apache.jena.update.UpdateRequest;
import org.apache.jena.util.iterator.ExtendedIterator;
import org.apache.jena.util.iterator.NiceIterator;
import org.apache.jena.vocabulary.RDF;
/**
* Class to build update requests.
*
*/
public class UpdateBuilder {
private final PrefixHandler prefixHandler;
private final WhereQuadHolder whereProcessor;
private List<QuadHolder> inserts = new ArrayList<QuadHolder>();
private List<QuadHolder> deletes = new ArrayList<QuadHolder>();
private Map<Var, Node> values;
private Node with;
/**
* Creates an UpdateBuilder with an empty prefix mapping.
*/
public UpdateBuilder() {
this.prefixHandler = new PrefixHandler();
this.whereProcessor = new WhereQuadHolder(prefixHandler);
this.values = new HashMap<Var, Node>();
this.with = null;
}
/**
* Creates an UpdateBuilder with the prefixes defined in the prolog clause.
* <b>May modify the contents of the prefix mapping in the prolog handler</b>
*
* @param prologClause the default prefixes for this builder.
*/
public UpdateBuilder(PrologClause<?> prologClause) {
this(prologClause.getPrologHandler().getPrefixes());
}
/**
* Creates an UpdateBuilder with the specified PrefixMapping. <b>May modify the
* contents of the prefix mapping</b>
*
* @param pMap the prefix mapping to use.
*/
public UpdateBuilder(PrefixMapping pMap) {
this.prefixHandler = new PrefixHandler(pMap);
this.whereProcessor = new WhereQuadHolder(prefixHandler);
this.values = new HashMap<Var, Node>();
this.with = null;
}
/**
* Convert a collection of QuadHolder to an iterator on Quads.
*
* @param holders the Collection of QuadHolder objects
* @return an iterator over the Quads.
*/
private ExtendedIterator<Quad> getQuads(Collection<QuadHolder> holders) {
ExtendedIterator<Quad> result = NiceIterator.emptyIterator();
for (QuadHolder holder : holders) {
result = result.andThen(holder.setValues(values).getQuads());
}
return result;
}
/**
* Checks that no deletes or inserts have been added to the builder.
* @return true if there are no delete or insert statements.
*/
public boolean isEmpty() {
return deletes.isEmpty() && inserts.isEmpty();
}
/**
* Build the update.
*
* <b>Note: the update does not include the prefix statements</b> use
* buildRequest() or appendTo() methods to include the prefix statements.
*
* @return the update.
*/
public Update build() {
if (isEmpty()) {
throw new IllegalStateException("At least one delete or insert must be specified");
}
if (whereProcessor.isEmpty()) {
return buildNoWhere();
}
return buildWhere();
}
/**
* Build as an UpdateRequest with prefix mapping set.
*
* @return a new UpdateRequest
*/
public UpdateRequest buildRequest() {
UpdateRequest req = new UpdateRequest(build());
req.setPrefixMapping(prefixHandler.getPrefixes());
return req;
}
/**
* Appends the new Update to the UpdateRequest.
*
* @param req the UpdateRequest to append this Update to.
* @return the req parameter for chaining.
*/
public UpdateRequest appendTo(UpdateRequest req) {
req.add(build());
for (Map.Entry<String, String> entry : prefixHandler.getPrefixes().getNsPrefixMap().entrySet()) {
req.setPrefix(entry.getKey(), entry.getValue());
}
return req;
}
// build updates without where clauses
private Update buildNoWhere() {
if (inserts.isEmpty()) {
QuadDataAcc quadData = new QuadDataAcc(getQuads(deletes).mapWith(new Function<Quad, Quad>() {
@Override
public Quad apply(Quad arg0) {
return check(arg0);
}
}).toList());
return new UpdateDataDelete(quadData);
}
if (deletes.isEmpty()) {
QuadDataAcc quadData = new QuadDataAcc(getQuads(inserts).mapWith(new Function<Quad, Quad>() {
@Override
public Quad apply(Quad t) {
return check(t);
}
}).toList());
return new UpdateDataInsert(quadData);
}
throw new IllegalStateException("Can not have both insert and delete without a where clause");
}
// build updates with where clauses
private Update buildWhere() {
UpdateModify retval = new UpdateModify();
if (with != null) {
Node graph = values.get(with);
if (graph == null) {
graph = with;
}
retval.setWithIRI(graph);
}
QuadAcc acc;
Iterator<Quad> iter;
if (!inserts.isEmpty()) {
retval.setHasInsertClause(true);
acc = retval.getInsertAcc();
iter = getQuads(inserts);
while (iter.hasNext()) {
acc.addQuad(iter.next());
}
}
if (!deletes.isEmpty()) {
retval.setHasDeleteClause(true);
acc = retval.getDeleteAcc();
iter = getQuads(deletes);
while (iter.hasNext()) {
acc.addQuad(iter.next());
}
}
retval.setElement(whereProcessor.setVars(values).build());
return retval;
}
/**
* Make a triple path from the objects.
*
* For subject, predicate and objects nodes
* <ul>
* <li>Will return Node.ANY if object is null.</li>
* <li>Will return the enclosed Node from a FrontsNode</li>
* <li>Will return the object if it is a Node.</li>
* <li>If the object is a String
* <ul>
* <li>For <code>predicate</code> only will attempt to parse as a path</li>
* <li>for subject, predicate and object will call NodeFactoryExtra.parseNode()
* using the currently defined prefixes if the object is a String</li>
* </ul>
* </li>
* <li>Will create a literal representation if the parseNode() fails or for any
* other object type.</li>
* </ul>
*
* @param s The subject object
* @param p the predicate object
* @param o the object object.
* @return a TriplePath
* @deprecatd use {@link #makeTriplePaths(Object, Object, Object)}
*/
@Deprecated(since="5.0.0")
public TriplePath makeTriplePath(Object s, Object p, Object o) {
final Object po = Converters.makeNodeOrPath(p, prefixHandler.getPrefixes());
if (po instanceof Path) {
return new TriplePath(makeNode(s), (Path) po, makeNode(o));
}
return new TriplePath(Triple.create(makeNode(s), (Node) po, makeNode(o)));
}
/**
* Make a collection of one or more {@code TriplePath} objects from the objects.
*
* Uses {@code Converters.makeTriplePaths} to perform the conversions using the prefixes
* defined in this UpdateBuilder.
*
* @param s The subject object
* @param p the predicate object
* @param o the object object.
* @return a collection of {@code TriplePath}s
*/
public Collection<TriplePath> makeTriplePaths(Object s, Object p, Object o) {
return Converters.makeTriplePaths(s, p, o, prefixHandler.getPrefixes());
}
/**
* Convert the object to a node.
*
* Shorthand for AbstractQueryBuilder.makeNode( o, prefixes )
*
* @see AbstractQueryBuilder#makeNode(Object)
*
* @param o the object to convert to a node.
* @return the Node.
*/
public Node makeNode(Object o) {
return Converters.makeNode(o, prefixHandler.getPrefixes());
}
/**
* Convert the object to a node.
*
* Shorthand for AbstractQueryBuilder.makeVar( o )
*
* @see Converters#makeVar(Object)
*
* @param o the object to convert to a var.
* @return the Var.
* @deprecated use {@link Converters#makeVar(Object)}
*/
@Deprecated
public Var makeVar(Object o) {
return Converters.makeVar(o);
}
/**
* Quote a string.
*
* Shorthand for AbstractQueryBuilder.quote( s )
*
* @see Converters#quoted(String)
*
* @deprecated Use quoted()
* @param s the string to quote.
* @return the quoted string.
* @deprecated use {@link Converters#quoted(String)}
*/
@Deprecated
public String quote(String s) {
return Converters.quoted(s);
}
/**
* Converts the {@code s,p,o} triple into a list of Triples. List will contain multiple
* triples if {@code s} or {@code o} are collections.
* @param s The subject object
* @param p the predicate object.
* @param o the object object.
* @return A list of triples.
*/
private List<Triple> makeTriples(Object s, Object p, Object o) {
return Converters.makeTriples(s, p, o, prefixHandler.getPrefixes());
}
/**
* Add a quad to the insert statement.
*
* Arguments are converted to nodes using the makeNode() method.
*
* @see #makeNode(Object)
* @param g the graph
* @param s the subject
* @param p the predicate
* @param o the object
* @return this builder for chaining.
*/
public UpdateBuilder addInsert(Object g, Object s, Object p, Object o) {
List<Triple> lst = makeTriples(s, p, o);
return lst.size()>1? addInsert(g, lst) : addInsert(g, lst.get(0));
}
/**
* Add a quad to the insert statement.
*
*
* @param quad the quad to add.
* @return this builder for chaining.
*/
public UpdateBuilder addInsert(Quad quad) {
inserts.add(new SingleQuadHolder(quad));
return this;
}
/**
* Add a triple to the insert statement.
*
* Arguments are converted to nodes using the makeNode() method.
*
* @see #makeNode(Object)
* @param s the subject
* @param p the predicate
* @param o the object
* @return this builder for chaining.
*/
public UpdateBuilder addInsert(Object s, Object p, Object o) {
List<Triple> lst = makeTriples(s, p, o);
return lst.size()>1? addInsert(lst) : addInsert(lst.get(0));
}
/**
* Add a triple to the insert statement.
*
* @param t the triple to add.
* @return this builder for chaining.
*/
public UpdateBuilder addInsert(Triple t) {
inserts.add(new SingleQuadHolder(t));
return this;
}
/**
* Add a triple in a specified graph to the insert statement.
*
* The graph object is converted by a call to makeNode().
*
* @see #makeNode(Object)
* @param g the graph for the triple.
* @param t the triple to add.
* @return this builder for chaining.
*/
public UpdateBuilder addInsert(Object g, Triple t) {
Quad q = new Quad(makeNode(g), t);
inserts.add(new SingleQuadHolder(q));
return this;
}
/**
* Add all the statements in the model to the insert statement. Uses
* Quad.defaultGraphNodeGenerated as the graph name.
*
* @param model The model to insert.
* @return this builder for chaining.
*/
public UpdateBuilder addInsert(Model model) {
inserts.add(new ModelQuadHolder(model));
return this;
}
/**
* Add all the triples in the model to the insert statement. Uses
* Quad.defaultGraphNodeGenerated as the graph name.
*
* @param collection The triples to insert.
* @return this builder for chaining.
* @see Quad#defaultGraphNodeGenerated
*/
public UpdateBuilder addInsert(Collection<Triple> collection) {
inserts.add(new CollectionQuadHolder(collection));
return this;
}
/**
* Add all the quads in the collection to the insert statement.
*
* @param collection The quads to insert.
* @return this builder for chaining.
*/
public UpdateBuilder addInsertQuads(Collection<Quad> collection) {
inserts.add(new QuadCollectionHolder(collection));
return this;
}
/**
* Add all the triples to the insert statement. Uses
* Quad.defaultGraphNodeGenerated as the graph name.
*
* @param iter The iterator of triples to insert.
* @return this builder for chaining.
* @see Quad#defaultGraphNodeGenerated
*/
public UpdateBuilder addInsert(Iterator<Triple> iter) {
inserts.add(new CollectionQuadHolder(iter));
return this;
}
/**
* Add all the statements in the model a specified graph to the insert
* statement.
*
* The graph object is converted by a call to makeNode().
*
* @see #makeNode(Object)
* @param g the graph for the triple.
* @param model the model to add.
* @return this builder for chaining.
*/
public UpdateBuilder addInsert(Object g, Model model) {
inserts.add(new ModelQuadHolder(makeNode(g), model));
return this;
}
/**
* Add triples to the insert statement.
*
* @param g the name of the graph to add the triples to.
* @param collection The triples to insert.
* @return this builder for chaining.
*/
public UpdateBuilder addInsert(Object g, Collection<Triple> collection) {
inserts.add(new CollectionQuadHolder(makeNode(g), collection));
return this;
}
/**
* Add triples to the insert statement.
*
* @param g the name of the graph to add the triples to.
* @param iter The iterator of triples to insert.
* @return this builder for chaining.
*/
public UpdateBuilder addInsert(Object g, Iterator<Triple> iter) {
inserts.add(new CollectionQuadHolder(makeNode(g), iter));
return this;
}
/**
* Add the statements from the where clause in the specified query builder to
* the insert statement. Uses Quad.defaultGraphNodeGenerated as the graph name.
*
* @see #makeNode(Object)
* @see Quad#defaultGraphNodeGenerated
* @param queryBuilder The query builder to extract the where clause from.
* @return this builder for chaining.
*/
public UpdateBuilder addInsert(AbstractQueryBuilder<?> queryBuilder) {
inserts.add(new QBQuadHolder(queryBuilder));
return this;
}
/**
* Add the statements from the where clause in the specified query builder to
* the insert statements for the specified graph.
*
* The graph object is converted by a call to makeNode().
*
* @see #makeNode(Object)
* @param graph the graph to add the statements to.
* @param queryBuilder The query builder to extract the where clause from.
* @return this builder for chaining.
*/
public UpdateBuilder addInsert(Object graph, AbstractQueryBuilder<?> queryBuilder) {
inserts.add(new QBQuadHolder(makeNode(graph), queryBuilder));
return this;
}
/**
* Add a quad to the delete statement.
*
* Arguments are converted to nodes using the makeNode() method.
*
* @see #makeNode(Object)
* @param g the graph
* @param s the subject
* @param p the predicate
* @param o the object
* @return this builder for chaining.
*/
public UpdateBuilder addDelete(Object g, Object s, Object p, Object o) {
List<Triple> lst = makeTriples(s, p, o);
return lst.size()>1? addDelete(g, lst) : addDelete(g, lst.get(0));
}
/**
* Add a quad to the delete statement.
*
* @param quad the quad to add.
* @return this builder for chaining.
*/
public UpdateBuilder addDelete(Quad quad) {
deletes.add(new SingleQuadHolder(quad));
return this;
}
/**
* Add all the quads collection to the delete statement.
*
* @param collection The quads to insert.
* @return this builder for chaining.
*/
public UpdateBuilder addDeleteQuads(Collection<Quad> collection) {
deletes.add(new QuadCollectionHolder(collection));
return this;
}
/**
* Add a triple to the delete statement.
*
* Arguments are converted to nodes using the makeNode() method.
*
* @see #makeNode(Object)
* @param s the subject
* @param p the predicate
* @param o the object
* @return this builder for chaining.
*/
public UpdateBuilder addDelete(Object s, Object p, Object o) {
List<Triple> lst = makeTriples(s, p, o);
return lst.size()>1? addDelete(lst) : addDelete(lst.get(0));
}
/**
* Add a triple to the delete statement. Uses Quad.defaultGraphNodeGenerated as
* the graph name.
*
* @param t the triple to add.
* @return this builder for chaining.
* @see Quad#defaultGraphNodeGenerated
*/
public UpdateBuilder addDelete(Triple t) {
deletes.add(new SingleQuadHolder(t));
return this;
}
/**
* Add a triple to the delete statement.
*
* The graph object is converted by a call to makeNode().
*
* @see #makeNode(Object)
* @param g the graph for the triple.
* @param t the triple to add.
* @return this builder for chaining.
*/
public UpdateBuilder addDelete(Object g, Triple t) {
Quad q = new Quad(makeNode(g), t);
deletes.add(new SingleQuadHolder(q));
return this;
}
/**
* Add all the statements in the model to the delete statement. Uses
* Quad.defaultGraphNodeGenerated as the graph name.
*
* @param model The model to insert.
* @return this builder for chaining.
* @see Quad#defaultGraphNodeGenerated
*/
public UpdateBuilder addDelete(Model model) {
deletes.add(new ModelQuadHolder(model));
return this;
}
/**
* Add all triples to the delete statement. Uses Quad.defaultGraphNodeGenerated
* as the graph name.
*
* @param collection The collection of triples to insert.
* @return this builder for chaining.
* @see Quad#defaultGraphNodeGenerated
*/
public UpdateBuilder addDelete(Collection<Triple> collection) {
deletes.add(new CollectionQuadHolder(collection));
return this;
}
/**
* Add all the triples in the iterator to the delete statement. Uses
* Quad.defaultGraphNodeGenerated as the graph name.
*
* @param iter The iterator of triples to insert.
* @return this builder for chaining.
* @see Quad#defaultGraphNodeGenerated
*/
public UpdateBuilder addDelete(Iterator<Triple> iter) {
deletes.add(new CollectionQuadHolder(iter));
return this;
}
/**
* Add all the statements in the model a specified graph to the delete
* statement.
*
* The graph object is converted by a call to makeNode().
*
* @see #makeNode(Object)
* @param g the graph for the triples.
* @param model the model to add.
* @return this builder for chaining.
*/
public UpdateBuilder addDelete(Object g, Model model) {
deletes.add(new ModelQuadHolder(makeNode(g), model));
return this;
}
/**
* Add all the statements in the model to the delete statement.
*
* @param g the graph for the triples.
* @param collection The collection of triples to insert.
* @return this builder for chaining.
*/
public UpdateBuilder addDelete(Object g, Collection<Triple> collection) {
deletes.add(new CollectionQuadHolder(makeNode(g), collection));
return this;
}
/**
* Add all the statements in the model to the delete statement.
*
* @param g the graph for the triples.
* @param iter The iterator of triples to insert.
* @return this builder for chaining.
*/
public UpdateBuilder addDelete(Object g, Iterator<Triple> iter) {
deletes.add(new CollectionQuadHolder(makeNode(g), iter));
return this;
}
/**
* Add the statements from the where clause in the specified query builder to
* the delete statement. Uses Quad.defaultGraphNodeGenerated as the graph name.
*
* @see #makeNode(Object)
* @see Quad#defaultGraphNodeGenerated
* @param queryBuilder The query builder to extract the where clause from.
* @return this builder for chaining.
*/
public UpdateBuilder addDelete(AbstractQueryBuilder<?> queryBuilder) {
deletes.add(new QBQuadHolder(queryBuilder));
return this;
}
/**
* Add the statements from the where clause in the specified query builder to
* the delete statements for the specified graph.
*
* The graph object is converted by a call to makeNode().
*
* @see #makeNode(Object)
* @param graph the graph to add the statements to.
* @param queryBuilder The query builder to extract the where clause from.
* @return this builder for chaining.
*/
public UpdateBuilder addDelete(Object graph, AbstractQueryBuilder<?> queryBuilder) {
deletes.add(new QBQuadHolder(makeNode(graph), queryBuilder));
return this;
}
/**
* Add the prefix to the prefix mapping.
*
* @param pfx the prefix to add.
* @param uri the uri for the prefix.
* @return this builder for chaining
*/
public UpdateBuilder addPrefix(String pfx, Resource uri) {
return addPrefix(pfx, uri.getURI());
}
/**
* Add the prefix to the prefix mapping.
*
* @param pfx the prefix to add.
* @param uri the uri for the prefix.
* @return this builder for chaining
*/
public UpdateBuilder addPrefix(String pfx, Node uri) {
return addPrefix(pfx, uri.getURI());
}
/**
* Add the prefix to the prefix mapping.
*
* @param pfx the prefix to add.
* @param uri the uri for the prefix.
* @return this builder for chaining
*/
public UpdateBuilder addPrefix(String pfx, String uri) {
prefixHandler.addPrefix(pfx, uri);
return this;
}
/**
* Add the prefixes to the prefix mapping.
*
* @param prefixes the prefixes to add.
* @return this builder for chaining
*/
public UpdateBuilder addPrefixes(Map<String, String> prefixes) {
prefixHandler.addPrefixes(prefixes);
return this;
}
/**
* Add the prefixes to the prefix mapping.
*
* @param prefixes the prefix mapping to add.
* @return this builder for chaining
*/
public UpdateBuilder addPrefixes(PrefixMapping prefixes) {
prefixHandler.addPrefixes(prefixes);
return this;
}
/**
* Get an ExprFactory that uses the prefixes from this builder.
*
* @return the ExpressionFactory.
*/
public ExprFactory getExprFactory() {
return prefixHandler.getExprFactory();
}
/**
* Set a variable replacement. During build all instances of var in the query
* will be replaced with value. If value is null the replacement is cleared.
*
* @param var The variable to replace
* @param value The value to replace it with or null to remove the replacement.
*/
public void setVar(Var var, Node value) {
if (value == null) {
values.remove(var);
} else {
values.put(var, value);
}
}
/**
* Set a variable replacement. During build all instances of var in the query
* will be replaced with value. If value is null the replacement is cleared.
*
* See {@link #makeVar} for conversion of the var param. See {@link #makeNode}
* for conversion of the value param.
*
* @param var The variable to replace.
* @param value The value to replace it with or null to remove the replacement.
*/
public void setVar(Object var, Object value) {
if (value == null) {
setVar(Converters.makeVar(var), null);
} else {
setVar(Converters.makeVar(var), makeNode(value));
}
}
private Quad check(Quad q) {
if (Var.isVar(q.getGraph()))
throw new QueryParseException("Variables not permitted in data quad", -1, -1);
if (Var.isVar(q.getSubject()) || Var.isVar(q.getPredicate()) || Var.isVar(q.getObject()))
throw new QueryParseException("Variables not permitted in data quad", -1, -1);
if (q.getSubject().isLiteral())
throw new QueryParseException("Literals not allowed as subjects in data", -1, -1);
return q;
}
/**
* Add all where attributes from the Where Handler argument.
*
* @param whereHandler The Where Handler to copy from.
*/
public UpdateBuilder addAll(WhereHandler whereHandler) {
whereProcessor.addAll(whereHandler);
return this;
}
/**
* Add the triple path to the where clause
*
* @param t The triple path to add.
* @throws IllegalArgumentException If the triple path is not a valid triple
* path for a where clause.
*/
public UpdateBuilder addWhere(TriplePath t) throws IllegalArgumentException {
whereProcessor.addWhere(t);
return this;
}
/**
* Add the WhereClause
*
* @param whereClause
* @throws IllegalArgumentException If the triple path is not a valid triple
* path for a where clause.
*/
public UpdateBuilder addWhere(WhereClause<?> whereClause) throws IllegalArgumentException {
whereProcessor.addAll(whereClause.getWhereHandler());
return this;
}
/**
* Add an optional triple to the where clause
*
* @param t The triple path to add.
* @return The Builder for chaining.
* @throws IllegalArgumentException If the triple is not a valid triple for a
* where clause.
*/
public UpdateBuilder addOptional(TriplePath t) throws IllegalArgumentException {
whereProcessor.addOptional(t);
return this;
}
/**
* Add an optional triple to the where clause
*
* @param collection The collection of {@code TriplePath} path to add.
* @return The Builder for chaining.
* @throws IllegalArgumentException If the triple is not a valid triple for a
* where clause.
*/
public UpdateBuilder addOptional(Collection<TriplePath> collection) throws IllegalArgumentException {
whereProcessor.addOptional(collection);
return this;
}
/**
* Add the contents of a where handler as an optional statement.
*
* @param whereHandler The where handler to use as the optional statement.
*/
public UpdateBuilder addOptional(WhereHandler whereHandler) {
whereProcessor.addOptional(whereHandler);
return this;
}
/**
* Add an expression string as a filter.
*
* @param expression The expression string to add.
* @return The Builder for chaining.
*/
public UpdateBuilder addFilter(String expression) {
whereProcessor.addFilter(expression);
return this;
}
/**
* Add a subquery to the where clause.
*
* @param subQuery The sub query to add.
* @return The Builder for chaining.
*/
public UpdateBuilder addSubQuery(AbstractQueryBuilder<?> subQuery) {
whereProcessor.addSubQuery(subQuery);
return this;
}
/**
* Add a union to the where clause.
*
* @param subQuery The subquery to add as the union.
* @return The Builder for chaining.
*/
public UpdateBuilder addUnion(AbstractQueryBuilder<?> subQuery) {
whereProcessor.addUnion(subQuery);
return this;
}
/**
* Add a graph to the where clause.
*
* @param graph The name of the graph.
* @param subQuery The where handler that defines the graph.
*/
public UpdateBuilder addGraph(Node graph, WhereHandler subQuery) {
whereProcessor.addGraph(graph, subQuery);
return this;
}
/**
* Add a binding to the where clause.
*
* @param expr The expression to bind.
* @param var The variable to bind it to.
*/
public UpdateBuilder addBind(Expr expr, Var var) {
whereProcessor.addBind(expr, var);
return this;
}
/**
* Add a binding to the where clause.
*
* @param expression The expression to bind.
* @param var The variable to bind it to.
*/
public UpdateBuilder addBind(String expression, Var var) {
whereProcessor.addBind(expression, var);
return this;
}
/**
* Create a list node from a list of objects as per RDF Collections.
*
* http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#collections
*
* See {@link AbstractQueryBuilder#makeNode} for conversion of the param values.
* <p>
* usage:
* <ul>
* <li>list( param1, param2, param3, ... )</li>
* <li>addWhere( list( param1, param2, param3, ... ), p, o )</li>
* <li>addOptional( list( param1, param2, param3, ... ), p, o )</li>
* </ul>
*
* @param objs the list of objects for the list.
* @return the first blank node in the list.
* @deprecated use makeList
* @see #makeList(Object...)
*/
@Deprecated(since="5.0.0")
public Node list(Object... objs) {
Node retval = NodeFactory.createBlankNode();
Node lastObject = retval;
for (int i = 0; i < objs.length; i++) {
Node n = makeNode(objs[i]);
addWhere(new TriplePath(Triple.create(lastObject, RDF.first.asNode(), n)));
if (i + 1 < objs.length) {
Node nextObject = NodeFactory.createBlankNode();
addWhere(new TriplePath(Triple.create(lastObject, RDF.rest.asNode(), nextObject)));
lastObject = nextObject;
} else {
addWhere(new TriplePath(Triple.create(lastObject, RDF.rest.asNode(), RDF.nil.asNode())));
}
}
return retval;
}
/**
* Create a list node from a list of objects as per RDF Collections.
*
* http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#collections
*
* See {@link AbstractQueryBuilder#makeNode} for conversion of the param values.
* <p>
* usage:
* <ul>
* <li>list( param1, param2, param3, ... )</li>
* <li>addWhere( list( param1, param2, param3, ... ), p, o )</li>
* <li>addOptional( list( param1, param2, param3, ... ), p, o )</li>
* </ul>
*
* @param objs the list of objects for the list.
* @return the first blank node in the list.
*/
public Node makeList(Object... objs) {
Node retval = NodeFactory.createBlankNode();
Node lastObject = retval;
for (int i = 0; i < objs.length; i++) {
Node n = makeNode(objs[i]);
addWhere(new TriplePath(Triple.create(lastObject, RDF.first.asNode(), n)));
if (i + 1 < objs.length) {
Node nextObject = NodeFactory.createBlankNode();
addWhere(new TriplePath(Triple.create(lastObject, RDF.rest.asNode(), nextObject)));
lastObject = nextObject;
} else {
addWhere(new TriplePath(Triple.create(lastObject, RDF.rest.asNode(), RDF.nil.asNode())));
}
}
return retval;
}
/**
* Adds a triple to the where clause.
*
* @param t The triple path to add
* @return The Builder for chaining.
*/
public UpdateBuilder addWhere(Triple t) {
return addWhere(new TriplePath(t));
}
/**
* Adds a triple to the where clause.
*
* @param t The triple to add
* @return The Builder for chaining.
*/
public UpdateBuilder addWhere(FrontsTriple t) {
return addWhere(t.asTriple());
}
/**
* Adds a triple or triple path to the where clause.
*
* See {@link AbstractQueryBuilder#makeTriplePath} for conversion of the param
* values.
*
* @param s The subject.
* @param p The predicate.
* @param o The object.
* @return The Builder for chaining.
*/
public UpdateBuilder addWhere(Object s, Object p, Object o) {
makeTriplePaths(s, p, o).forEach(whereProcessor::addWhere);
return this;
}
/**
* Adds an optional triple to the where clause.
*
* @param t The triple to add
* @return The Builder for chaining.
*/
public UpdateBuilder addOptional(Triple t) {
return addOptional(new TriplePath(t));
}
/**
* Adds an optional triple as to the where clause.
*
* @param t The triple to add
* @return The Builder for chaining.
*/
public UpdateBuilder addOptional(FrontsTriple t) {
return addOptional(t.asTriple());
}
/**
* Adds an optional triple or triple path to the where clause.
*
* See {@link AbstractQueryBuilder#makeTriplePath} for conversion of the param
* values.
*
* @param s The subject.
* @param p The predicate.
* @param o The object.
* @return The Builder for chaining.
*/
public UpdateBuilder addOptional(Object s, Object p, Object o) {
makeTriplePaths(s, p, o).forEach(whereProcessor::addOptional);
return this;
}
/**
* Adds an optional group pattern to the where clause.
*
* @param t The select builder to add as an optional pattern
* @return The Builder for chaining.
*/
public UpdateBuilder addOptional(AbstractQueryBuilder<?> t) {
whereProcessor.addOptional(t.getWhereHandler());
return this;
}
/**
* Adds a filter to the where clause
*
* Use ExprFactory or NodeValue static or the AbstractQueryBuilder.makeExpr
* methods to create the expression.
*
* @see ExprFactory
* @see org.apache.jena.sparql.expr.NodeValue
* @see AbstractQueryBuilder#makeExpr(String)
*
* @param expression the expression to evaluate for the filter.
* @return The Builder for chaining.
*/
public UpdateBuilder addFilter(Expr expression) {
whereProcessor.addFilter(expression);
return this;
}
/**
* Add a graph statement to the query as per
* http://www.w3.org/TR/2013/REC-sparql11 -query-20130321/#rGraphGraphPattern.
*
* See {@link AbstractQueryBuilder#makeNode} for conversion of the graph param.
*
* @param graph The iri or variable identifying the graph.
* @param subQuery The graph to add.
* @return This builder for chaining.
*/
public UpdateBuilder addGraph(Object graph, AbstractQueryBuilder<?> subQuery) {
whereProcessor.addGraph(makeNode(graph), subQuery.getWhereHandler());
return this;
}
/**
* Add a bind statement to the query *
* http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rGraphGraphPattern.
*
* @param expression The expression to bind to the var.
* @param var The variable to bind to.
* @return This builder for chaining.
*/
public UpdateBuilder addBind(Expr expression, Object var) {
whereProcessor.addBind(expression, makeVar(var));
return this;
}
/**
* Add a bind statement to the query
* http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rGraphGraphPattern.
*
* @param expression The expression to bind to the var.
* @param var The variable to bind to.
* @return This builder for chaining.
*/
public UpdateBuilder addBind(String expression, Object var) {
whereProcessor.addBind(expression, makeVar(var));
return this;
}
/**
* Add a minus clause to the query.
*
* https://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rMinusGraphPattern
*
* @param t The select builder to add as a minus pattern
* @return this builder for chaining
*/
public UpdateBuilder addMinus(AbstractQueryBuilder<?> t) {
whereProcessor.addMinus(t);
return this;
}
/**
* Specify the graph for all inserts and deletes.
*
*
* @see Quad#defaultGraphNodeGenerated
* @param iri the IRI for the graph to use.
* @return this builder for chaining.
*/
public UpdateBuilder with(Object iri) {
if (iri == null) {
with = null;
}
Node n = makeNode(iri);
if (n.isLiteral()) {
throw new IllegalArgumentException(String.format("IRI '%s' must not be a literal", iri));
}
with = n;
return this;
}
/**
* Create a DeleteWhere from the where clause.
*
* @return a DeleteWhere update.
*/
public UpdateDeleteWhere buildDeleteWhere() {
QuadAcc quadAcc = new QuadAcc(whereProcessor.getQuads().toList());
return new UpdateDeleteWhere(quadAcc);
}
/**
* Create a DeleteWhere from the where clause.
*
* @param queryBuilder the query builder to extract the where clause from.
* @return a DeleteWhere update.
*/
public UpdateDeleteWhere buildDeleteWhere(AbstractQueryBuilder<?> queryBuilder) {
QuadAcc quadAcc = new QuadAcc(new QBQuadHolder(queryBuilder).getQuads().toList());
return new UpdateDeleteWhere(quadAcc);
}
}