You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by cl...@apache.org on 2014/10/15 20:42:27 UTC
[50/51] [partial] added missing querybuilder code.
http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder
----------------------------------------------------------------------
diff --git a/jena-extras/jena-querybuilder b/jena-extras/jena-querybuilder
deleted file mode 160000
index dc4dbdb..0000000
--- a/jena-extras/jena-querybuilder
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit dc4dbdb52854219a45fb9a4a8c51453e24054a08
diff --git a/jena-extras/jena-querybuilder/LICENSE b/jena-extras/jena-querybuilder/LICENSE
new file mode 100644
index 0000000..e06d208
--- /dev/null
+++ b/jena-extras/jena-querybuilder/LICENSE
@@ -0,0 +1,202 @@
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/jena-extras/jena-querybuilder/README.md b/jena-extras/jena-querybuilder/README.md
new file mode 100644
index 0000000..6e7ab47
--- /dev/null
+++ b/jena-extras/jena-querybuilder/README.md
@@ -0,0 +1,49 @@
+querybuilder
+============
+
+Query Builder for Jena. Implementations of Ask, Construct and Select builders that allow developers to create queries without resorting to StringBuilders or similar solutions.
+
+Each of the builders has a series of methods to define the query. Each method returns the builder for easy chaing. The example:
+
+```
+SelectBuilder sb = new SelectBuilder()
+ .addVar( "*" )
+ .addWhere( "?s", "?o", "?p" );
+
+Query q = sb.build();
+
+```
+
+produces `SELECT * WHERE { ?s ?o ?p . }`
+
+Template Usage
+==============
+
+In addition to making it easier to build valid queries the QueryBuilder has a clone method. Using this a developer can create as "Template" query and add to it as necessary.
+
+for example using the above query as the "template" the this code:
+
+```
+SelectBuilder sb2 = sb.clone();
+sb2.addPrefix( "foaf", "http://xmlns.com/foaf/0.1/" ).addWhere( ?s, RDF.type, foaf:Person)
+```
+
+produces `PREFIX foaf: http://xmlns.com/foaf/0.1/ SELECT * WHERE { ?s ?o ?p . ?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> foaf:person . }`
+
+Prepared Statement Usage
+========================
+
+The query builders have the ability to replace variables with other values. This can be
+
+```
+SelectBuilder sb = new SelectBuilder()
+ .addVar( "*" )
+ .addWhere( "?s", "?o", "?p" );
+
+sb.setVar( Var.alloc( "?p" ), NodeFactory.createURI( "http://xmlns.com/foaf/0.1/Person" )
+Query q = sb.build();
+
+```
+
+produces `SELECT * WHERE { ?s ?o <http://xmlns.com/foaf/0.1/Person> . }`
+
diff --git a/jena-extras/jena-querybuilder/license-header.txt b/jena-extras/jena-querybuilder/license-header.txt
new file mode 100644
index 0000000..a9ac967
--- /dev/null
+++ b/jena-extras/jena-querybuilder/license-header.txt
@@ -0,0 +1,14 @@
+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.
\ No newline at end of file
diff --git a/jena-extras/jena-querybuilder/pom.xml b/jena-extras/jena-querybuilder/pom.xml
new file mode 100644
index 0000000..da311b5
--- /dev/null
+++ b/jena-extras/jena-querybuilder/pom.xml
@@ -0,0 +1,48 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>jena-querybuilder</artifactId>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>apache-jena-libs</artifactId>
+ <type>pom</type>
+ </dependency>
+ <dependency>
+ <groupId>org.xenei</groupId>
+ <artifactId>junit-contracts</artifactId>
+ </dependency>
+ </dependencies>
+ <name>Apache Jena Query Builder- jena-querybulder</name>
+ <inceptionYear>2014</inceptionYear>
+ <organization>
+ <name>The Apache Software Foundation</name>
+ <url>http://www.apache.org/</url>
+ </organization>
+ <properties>
+
+ </properties>
+ <scm>
+ <!-- <url>https://svn.apache.org/repos/asf/jena/Experimental/jena-common/</url>
+ <connection>scm:svn:https://svn.apache.org/repos/asf/jena/Experimental/jena-common/</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/jena/Experimental/jena-common/</developerConnection>
+ -->
+ </scm>
+ <parent>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-extras</artifactId>
+ <relativePath>..</relativePath>
+ <version>2.12.2-SNAPSHOT</version>
+ </parent>
+ <description>A utility package to simplify the building of ARQ queries in code. Provides both a simple builder interface for queries as well as simple prepared statement processing.</description>
+</project>
\ No newline at end of file
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/AbstractQueryBuilder.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/AbstractQueryBuilder.java
new file mode 100644
index 0000000..baea059
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/AbstractQueryBuilder.java
@@ -0,0 +1,362 @@
+/*
+ * 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.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+
+import org.apache.jena.arq.querybuilder.clauses.ConstructClause;
+import org.apache.jena.arq.querybuilder.clauses.DatasetClause;
+import org.apache.jena.arq.querybuilder.clauses.PrologClause;
+import org.apache.jena.arq.querybuilder.clauses.SelectClause;
+import org.apache.jena.arq.querybuilder.clauses.SolutionModifierClause;
+import org.apache.jena.arq.querybuilder.clauses.WhereClause;
+import org.apache.jena.arq.querybuilder.handlers.ConstructHandler;
+import org.apache.jena.arq.querybuilder.handlers.DatasetHandler;
+import org.apache.jena.arq.querybuilder.handlers.Handler;
+import org.apache.jena.arq.querybuilder.handlers.PrologHandler;
+import org.apache.jena.arq.querybuilder.handlers.SelectHandler;
+import org.apache.jena.arq.querybuilder.handlers.SolutionModifierHandler;
+import org.apache.jena.arq.querybuilder.handlers.WhereHandler;
+import org.apache.jena.riot.RiotException;
+import org.apache.jena.riot.system.PrefixMapFactory;
+
+import com.hp.hpl.jena.graph.FrontsNode;
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.NodeFactory;
+import com.hp.hpl.jena.graph.impl.LiteralLabelFactory;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.rdf.model.Resource;
+import com.hp.hpl.jena.sparql.ARQInternalErrorException;
+import com.hp.hpl.jena.sparql.core.Var;
+import com.hp.hpl.jena.sparql.expr.ExprVar;
+import com.hp.hpl.jena.sparql.util.NodeFactoryExtra;
+
+/**
+ * Base class for all QueryBuilders.
+ *
+ * @param <T>
+ * The derived class type. Used for return types.
+ */
+public abstract class AbstractQueryBuilder<T extends AbstractQueryBuilder<T>>
+ implements Cloneable, PrologClause<T> {
+
+ // all queries have prologs
+ protected PrologHandler prologHandler;
+ // the query this builder is building
+ protected Query query;
+ // a map of vars to nodes for replacement during build.
+ private Map<Var, Node> values;
+
+ /**
+ * Make a Node from an object.
+ * <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>Will call NodeFactoryExtra.parseNode() using the currently defined
+ * prefixes if the object is a String</li>
+ * <li>Will create a literal representation if the parseNode() fails or for
+ * any other object type.</li>
+ * </ul>
+ *
+ * @param o
+ * The object to convert. (may be null)
+ * @return The Node value.
+ */
+ public Node makeNode(Object o) {
+ if (o == null) {
+ return Node.ANY;
+ }
+ if (o instanceof FrontsNode) {
+ return ((FrontsNode) o).asNode();
+ }
+
+ if (o instanceof Node) {
+ return (Node) o;
+ }
+ if (o instanceof String) {
+ try {
+ return NodeFactoryExtra.parseNode((String) o, PrefixMapFactory
+ .createForInput(query.getPrefixMapping()));
+ } catch (RiotException e) {
+ // expected in some cases -- do nothing
+ }
+
+ }
+ return NodeFactory.createLiteral(LiteralLabelFactory.create(o));
+ }
+
+ /**
+ * Make a Var from an object.
+ * <ul>
+ * <li>Will return Var.ANON if object is null.</li>
+ * <li>Will return null if the object is "*" or Node_RuleVariable.WILD</li>
+ * <li>Will return the object if it is a Var</li>
+ * <li>Will return resolve FrontsNode to Node and then resolve to Var</li>
+ * <li>Will return resolve Node if the Node implements Node_Variable,
+ * otherwise throws an NotAVariableException (instance of
+ * ARQInternalErrorException)</li>
+ * <li>Will return ?x if object is "?x"</li>
+ * <li>Will return ?x if object is "x"</li>
+ * <li>Will return the enclosed Var of a ExprVar</li>
+ * <li>For all other objects will return the "?" prefixed to the toString()
+ * value.</li>
+ * </ul>
+ *
+ * @param o
+ * The object to convert.
+ * @return the Var value.
+ * @throws ARQInternalErrorException
+ */
+ public Var makeVar(Object o) throws ARQInternalErrorException {
+ if (o == null) {
+ return Var.ANON;
+ }
+ if (o instanceof Var) {
+ return (Var) o;
+ }
+ Var retval = null;
+ if (o instanceof FrontsNode) {
+ retval = Var.alloc(((FrontsNode) o).asNode());
+ } else if (o instanceof Node) {
+ retval = Var.alloc((Node) o);
+ } else if (o instanceof ExprVar) {
+ retval = Var.alloc((ExprVar) o);
+ } else {
+ retval = Var.alloc(Var.canonical(o.toString()));
+ }
+ if ("*".equals(Var.canonical(retval.toString()))) {
+ return null;
+ }
+ return retval;
+ }
+
+ /**
+ * Create a new query builder.
+ */
+ protected AbstractQueryBuilder() {
+ query = new Query();
+ prologHandler = new PrologHandler(query);
+ values = new HashMap<Var, Node>();
+ }
+
+ /**
+ * 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(makeVar(var), null);
+ } else {
+ setVar(makeVar(var), makeNode(value));
+ }
+ }
+
+ @Override
+ public PrologHandler getPrologHandler() {
+ return prologHandler;
+ }
+
+ @Override
+ public T addPrefix(String pfx, Resource uri) {
+ return addPrefix(pfx, uri.getURI());
+ }
+
+ @Override
+ public T addPrefix(String pfx, Node uri) {
+ return addPrefix(pfx, uri.getURI());
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T addPrefix(String pfx, String uri) {
+ prologHandler.addPrefix(pfx, uri);
+ return (T) this;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T addPrefixes(Map<String, String> prefixes) {
+ prologHandler.addPrefixes(prefixes);
+ return (T) this;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T setBase(String base) {
+ prologHandler.setBase(base);
+ return (T) this;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T setBase(Object base) {
+ setBase(makeNode(base).getURI());
+ return (T) this;
+ }
+
+ @Override
+ public String toString() {
+ return buildString();
+ }
+
+ /**
+ * Build the query as a string.
+ *
+ * @return the string representation of the query.
+ */
+ public final String buildString() {
+ return build().toString();
+ }
+
+ /**
+ * Build the query. Performs the var replacements as specified by
+ * setVar(var,node) calls.
+ *
+ * @return The query.
+ */
+ public final Query build() {
+ Query q = new Query();
+ try {
+ Field f = Query.class.getDeclaredField("queryType");
+ f.setAccessible(true);
+ f.set(q, query.getQueryType());
+ } catch (NoSuchFieldException e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ } catch (SecurityException e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ Stack<Handler> handlerStack = new Stack<Handler>();
+ PrologHandler ph = new PrologHandler(q);
+ handlerStack.push(ph);
+ ph.addAll(prologHandler);
+ ph.setVars(values);
+ if (this instanceof SelectClause) {
+ SelectHandler sh = new SelectHandler(q);
+ sh.addAll(((SelectClause<?>) this).getSelectHandler());
+ sh.setVars(values);
+ handlerStack.push(sh);
+ }
+ if (this instanceof ConstructClause) {
+ ConstructHandler ch = new ConstructHandler(q);
+ ch.addAll(((ConstructClause<?>) this).getConstructHandler());
+ ch.setVars(values);
+ handlerStack.push(ch);
+ }
+ if (this instanceof DatasetClause) {
+ DatasetHandler dh = new DatasetHandler(q);
+ dh.addAll(((DatasetClause<?>) this).getDatasetHandler());
+ dh.setVars(values);
+ handlerStack.push(dh);
+ }
+ if (this instanceof SolutionModifierClause) {
+ SolutionModifierHandler smh = new SolutionModifierHandler(q);
+ smh.addAll(((SolutionModifierClause<?>) this)
+ .getSolutionModifierHandler());
+ smh.setVars(values);
+ handlerStack.push(smh);
+ }
+ if (this instanceof WhereClause) {
+ WhereHandler wh = new WhereHandler(q);
+ wh.addAll(((WhereClause<?>) this).getWhereHandler());
+ wh.setVars(values);
+ handlerStack.push(wh);
+ }
+
+ while (!handlerStack.isEmpty()) {
+ handlerStack.pop().build();
+ }
+
+ return q;
+ }
+
+ /**
+ * Close the query.
+ *
+ * This can be used when the query would not normally parse as is required
+ * by the Query.clone() method.
+ *
+ * @param q2
+ * The query to clone
+ * @return A clone of the q2 param.
+ */
+ public static Query clone(Query q2) {
+ Query retval = new Query();
+ new PrologHandler(retval).addAll(new PrologHandler(q2));
+ new ConstructHandler(retval).addAll(new ConstructHandler(q2));
+ new DatasetHandler(retval).addAll(new DatasetHandler(q2));
+ new SolutionModifierHandler(retval).addAll(new SolutionModifierHandler(
+ q2));
+ new WhereHandler(retval).addAll(new WhereHandler(q2));
+ new SelectHandler(retval).addAll(new SelectHandler(q2));
+ return retval;
+ }
+
+ /**
+ * Rewrite a query replacing variables as specified in the values map.
+ *
+ * @param q2
+ * The query to rewrite
+ * @param values
+ * a Mapping of var to node for replacement.
+ * @return The new query with the specified vars replaced.
+ */
+ public static Query rewrite(Query q2, Map<Var, Node> values) {
+ new PrologHandler(q2).setVars(values);
+ new ConstructHandler(q2).setVars(values);
+ new DatasetHandler(q2).setVars(values);
+ new SolutionModifierHandler(q2).setVars(values);
+ new WhereHandler(q2).setVars(values);
+ new SelectHandler(q2).setVars(values);
+ return q2;
+ }
+}
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/AskBuilder.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/AskBuilder.java
new file mode 100644
index 0000000..edb6885
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/AskBuilder.java
@@ -0,0 +1,198 @@
+/*
+ * 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.Collection;
+
+import org.apache.jena.arq.querybuilder.clauses.DatasetClause;
+import org.apache.jena.arq.querybuilder.clauses.SolutionModifierClause;
+import org.apache.jena.arq.querybuilder.clauses.WhereClause;
+import org.apache.jena.arq.querybuilder.handlers.DatasetHandler;
+import org.apache.jena.arq.querybuilder.handlers.SolutionModifierHandler;
+import org.apache.jena.arq.querybuilder.handlers.WhereHandler;
+
+import com.hp.hpl.jena.graph.FrontsTriple;
+import com.hp.hpl.jena.graph.Triple;
+import com.hp.hpl.jena.sparql.lang.sparql_11.ParseException;
+
+/**
+ * Build an ASK query.
+ *
+ */
+public class AskBuilder extends AbstractQueryBuilder<AskBuilder> implements
+ DatasetClause<AskBuilder>, WhereClause<AskBuilder>,
+ SolutionModifierClause<AskBuilder> {
+ // the dataset handler
+ private final DatasetHandler datasetHandler;
+ // the where handler.
+ private final WhereHandler whereHandler;
+ // the solution modifier handler.
+ private final SolutionModifierHandler solutionModifier;
+
+ /**
+ * The constructor
+ */
+ public AskBuilder() {
+ super();
+ query.setQueryAskType();
+ datasetHandler = new DatasetHandler(query);
+ whereHandler = new WhereHandler(query);
+ solutionModifier = new SolutionModifierHandler(query);
+ }
+
+ @Override
+ public DatasetHandler getDatasetHandler() {
+ return datasetHandler;
+ }
+
+ @Override
+ public WhereHandler getWhereHandler() {
+ return whereHandler;
+ }
+
+ @Override
+ public AskBuilder clone() {
+ AskBuilder qb = new AskBuilder();
+ qb.prologHandler.addAll(prologHandler);
+ qb.datasetHandler.addAll(datasetHandler);
+ qb.solutionModifier.addAll(solutionModifier);
+ return qb;
+ }
+
+ @Override
+ public AskBuilder fromNamed(String graphName) {
+ datasetHandler.fromNamed(graphName);
+ return this;
+ }
+
+ @Override
+ public AskBuilder fromNamed(Collection<String> graphNames) {
+ datasetHandler.fromNamed(graphNames);
+ return this;
+ }
+
+ @Override
+ public AskBuilder from(String graphName) {
+ datasetHandler.from(graphName);
+ return this;
+ }
+
+ @Override
+ public AskBuilder from(Collection<String> graphName) {
+ datasetHandler.from(graphName);
+ return this;
+ }
+
+ @Override
+ public AskBuilder addWhere(Triple t) {
+ whereHandler.addWhere(t);
+ return this;
+ }
+
+ @Override
+ public AskBuilder addWhere(FrontsTriple t) {
+ whereHandler.addWhere(t.asTriple());
+ return this;
+ }
+
+ @Override
+ public AskBuilder addWhere(Object s, Object p, Object o) {
+ addWhere(new Triple(makeNode(s), makeNode(p), makeNode(o)));
+ return this;
+ }
+
+ @Override
+ public AskBuilder addOptional(Triple t) {
+ whereHandler.addOptional(t);
+ return this;
+ }
+
+ @Override
+ public AskBuilder addOptional(FrontsTriple t) {
+ whereHandler.addOptional(t.asTriple());
+ return this;
+ }
+
+ @Override
+ public AskBuilder addOptional(Object s, Object p, Object o) {
+ addOptional(new Triple(makeNode(s), makeNode(p), makeNode(o)));
+ return this;
+ }
+
+ @Override
+ public AskBuilder addFilter(String s) throws ParseException {
+ whereHandler.addFilter(s);
+ return this;
+ }
+
+ @Override
+ public AskBuilder addSubQuery(SelectBuilder subQuery) {
+ prologHandler.addAll(subQuery.getPrologHandler());
+ whereHandler.addSubQuery(subQuery);
+ return this;
+ }
+
+ @Override
+ public AskBuilder addUnion(SelectBuilder subQuery) {
+ whereHandler.addUnion(subQuery);
+ return this;
+ }
+
+ @Override
+ public AskBuilder addGraph(Object graph, SelectBuilder subQuery) {
+ prologHandler.addAll(subQuery.getPrologHandler());
+ whereHandler.addGraph(makeNode(graph), subQuery.getWhereHandler());
+ return this;
+ }
+
+ @Override
+ public AskBuilder addOrderBy(String orderBy) {
+ solutionModifier.addOrderBy(orderBy);
+ return this;
+ }
+
+ @Override
+ public AskBuilder addGroupBy(String groupBy) {
+ solutionModifier.addGroupBy(groupBy);
+ return this;
+ }
+
+ @Override
+ public AskBuilder addHaving(String having) throws ParseException {
+ solutionModifier.addHaving(having);
+ return this;
+ }
+
+ @Override
+ public AskBuilder setLimit(int limit) {
+ solutionModifier.setLimit(limit);
+ return this;
+ }
+
+ @Override
+ public AskBuilder setOffset(int offset) {
+ solutionModifier.setOffset(offset);
+ return this;
+ }
+
+ @Override
+ public SolutionModifierHandler getSolutionModifierHandler() {
+ return solutionModifier;
+ }
+
+}
\ No newline at end of file
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/ConstructBuilder.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/ConstructBuilder.java
new file mode 100644
index 0000000..eddc764
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/ConstructBuilder.java
@@ -0,0 +1,244 @@
+/*
+ * 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.Collection;
+
+import org.apache.jena.arq.querybuilder.clauses.ConstructClause;
+import org.apache.jena.arq.querybuilder.clauses.DatasetClause;
+import org.apache.jena.arq.querybuilder.clauses.SolutionModifierClause;
+import org.apache.jena.arq.querybuilder.clauses.WhereClause;
+import org.apache.jena.arq.querybuilder.handlers.ConstructHandler;
+import org.apache.jena.arq.querybuilder.handlers.DatasetHandler;
+import org.apache.jena.arq.querybuilder.handlers.SolutionModifierHandler;
+import org.apache.jena.arq.querybuilder.handlers.WhereHandler;
+
+import com.hp.hpl.jena.graph.FrontsTriple;
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.Triple;
+import com.hp.hpl.jena.sparql.lang.sparql_11.ParseException;
+
+/**
+ * Build an Construct query.
+ *
+ */
+public class ConstructBuilder extends AbstractQueryBuilder<ConstructBuilder>
+ implements DatasetClause<ConstructBuilder>,
+ WhereClause<ConstructBuilder>,
+ SolutionModifierClause<ConstructBuilder>,
+ ConstructClause<ConstructBuilder> {
+
+ // the handlers used by this builder
+ private final DatasetHandler datasetHandler;
+ private final WhereHandler whereHandler;
+ private final SolutionModifierHandler solutionModifier;
+ private final ConstructHandler constructHandler;
+
+ /**
+ * Constructor
+ */
+ public ConstructBuilder() {
+ super();
+ query.setQueryConstructType();
+ datasetHandler = new DatasetHandler(query);
+ whereHandler = new WhereHandler(query);
+ solutionModifier = new SolutionModifierHandler(query);
+ constructHandler = new ConstructHandler(query);
+ }
+
+ @Override
+ public DatasetHandler getDatasetHandler() {
+ return datasetHandler;
+ }
+
+ @Override
+ public WhereHandler getWhereHandler() {
+ return whereHandler;
+ }
+
+ @Override
+ public ConstructHandler getConstructHandler() {
+ return constructHandler;
+ }
+
+ @Override
+ public SolutionModifierHandler getSolutionModifierHandler() {
+ return solutionModifier;
+ }
+
+ @Override
+ public ConstructBuilder clone() {
+ ConstructBuilder qb = new ConstructBuilder();
+ qb.prologHandler.addAll(prologHandler);
+ qb.datasetHandler.addAll(datasetHandler);
+ qb.whereHandler.addAll(whereHandler);
+ qb.solutionModifier.addAll(solutionModifier);
+ qb.constructHandler.addAll(constructHandler);
+ return qb;
+ }
+
+ @Override
+ public ConstructBuilder fromNamed(String graphName) {
+ datasetHandler.fromNamed(graphName);
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder fromNamed(Collection<String> graphNames) {
+ datasetHandler.fromNamed(graphNames);
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder from(String graphName) {
+ datasetHandler.from(graphName);
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder from(Collection<String> graphName) {
+ datasetHandler.from(graphName);
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder addOrderBy(String orderBy) {
+ solutionModifier.addOrderBy(orderBy);
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder addGroupBy(String groupBy) {
+ solutionModifier.addGroupBy(groupBy);
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder addHaving(String having) throws ParseException {
+ solutionModifier.addHaving(having);
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder setLimit(int limit) {
+ solutionModifier.setLimit(limit);
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder setOffset(int offset) {
+ solutionModifier.setOffset(offset);
+ return this;
+ }
+
+ // convert a node to a string
+ private static String toString(Node node) {
+ if (node.isBlank()) {
+ return node.getBlankNodeLabel();
+ }
+ if (node.isLiteral()) {
+ return node.toString();
+ }
+ if (node.isURI()) {
+ return String.format("<%s>", node.getURI());
+ }
+ if (node.isVariable()) {
+ return String.format("?%s", node.getName());
+ }
+ return node.toString();
+ }
+
+ @Override
+ public ConstructBuilder addWhere(Triple t) {
+ whereHandler.addWhere(t);
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder addWhere(FrontsTriple t) {
+ whereHandler.addWhere(t.asTriple());
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder addWhere(Object s, Object p, Object o) {
+ addWhere(new Triple(makeNode(s), makeNode(p), makeNode(o)));
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder addOptional(Triple t) {
+ whereHandler.addOptional(t);
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder addOptional(FrontsTriple t) {
+ whereHandler.addOptional(t.asTriple());
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder addOptional(Object s, Object p, Object o) {
+ addOptional(new Triple(makeNode(s), makeNode(p), makeNode(o)));
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder addFilter(String s) throws ParseException {
+ whereHandler.addFilter(s);
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder addSubQuery(SelectBuilder subQuery) {
+ prologHandler.addAll(subQuery.prologHandler);
+ whereHandler.addSubQuery(subQuery);
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder addUnion(SelectBuilder subQuery) {
+ whereHandler.addUnion(subQuery);
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder addGraph(Object graph, SelectBuilder subQuery) {
+ prologHandler.addAll(subQuery.prologHandler);
+ whereHandler.addGraph(makeNode(graph), subQuery.getWhereHandler());
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder addConstruct(Triple t) {
+ constructHandler.addConstruct(t);
+ return this;
+ }
+
+ @Override
+ public ConstructBuilder addConstruct(FrontsTriple t) {
+ return addConstruct(t.asTriple());
+ }
+
+ @Override
+ public ConstructBuilder addConstruct(Object s, Object p, Object o) {
+ return addConstruct(new Triple(makeNode(s), makeNode(p), makeNode(o)));
+ }
+
+}
\ No newline at end of file
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/SelectBuilder.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/SelectBuilder.java
new file mode 100644
index 0000000..30b5ab0
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/SelectBuilder.java
@@ -0,0 +1,281 @@
+/*
+ * 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.Collection;
+import java.util.List;
+import org.apache.jena.arq.querybuilder.clauses.DatasetClause;
+import org.apache.jena.arq.querybuilder.clauses.SelectClause;
+import org.apache.jena.arq.querybuilder.clauses.SolutionModifierClause;
+import org.apache.jena.arq.querybuilder.clauses.WhereClause;
+import org.apache.jena.arq.querybuilder.handlers.DatasetHandler;
+import org.apache.jena.arq.querybuilder.handlers.SelectHandler;
+import org.apache.jena.arq.querybuilder.handlers.SolutionModifierHandler;
+import org.apache.jena.arq.querybuilder.handlers.WhereHandler;
+
+import com.hp.hpl.jena.graph.FrontsNode;
+import com.hp.hpl.jena.graph.FrontsTriple;
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.Triple;
+import com.hp.hpl.jena.sparql.core.Var;
+import com.hp.hpl.jena.sparql.lang.sparql_11.ParseException;
+
+/**
+ * Build a select query.
+ *
+ */
+public class SelectBuilder extends AbstractQueryBuilder<SelectBuilder>
+ implements DatasetClause<SelectBuilder>, WhereClause<SelectBuilder>,
+ SolutionModifierClause<SelectBuilder>, SelectClause<SelectBuilder> {
+
+ // the handlers.
+ private DatasetHandler datasetHandler;
+ private WhereHandler whereHandler;
+ private SolutionModifierHandler solutionModifier;
+ private SelectHandler selectHandler;
+
+ /**
+ * Constructor.
+ */
+ public SelectBuilder() {
+ super();
+ query.setQuerySelectType();
+ datasetHandler = new DatasetHandler(query);
+ whereHandler = new WhereHandler(query);
+ solutionModifier = new SolutionModifierHandler(query);
+ selectHandler = new SelectHandler(query);
+ }
+
+ @Override
+ public DatasetHandler getDatasetHandler() {
+ return datasetHandler;
+ }
+
+ @Override
+ public WhereHandler getWhereHandler() {
+ return whereHandler;
+ }
+
+ @Override
+ public SelectBuilder clone() {
+ SelectBuilder qb = new SelectBuilder();
+ qb.prologHandler.addAll(prologHandler);
+ qb.datasetHandler.addAll(datasetHandler);
+ qb.whereHandler.addAll(whereHandler);
+ qb.solutionModifier.addAll(solutionModifier);
+ qb.selectHandler.addAll(selectHandler);
+
+ return qb;
+ }
+
+ @Override
+ public SelectBuilder setDistinct(boolean state) {
+ selectHandler.setDistinct(state);
+ return this;
+ }
+
+ @Override
+ public SelectBuilder setReduced(boolean state) {
+ selectHandler.setReduced(state);
+ return this;
+ }
+
+ @Override
+ public SelectBuilder addVar(Object var) {
+ selectHandler.addVar(makeVar(var));
+ return this;
+ }
+
+ @Override
+ public List<Var> getVars() {
+ return selectHandler.getVars();
+ }
+
+ @Override
+ public SelectBuilder fromNamed(String graphName) {
+ datasetHandler.fromNamed(graphName);
+ return this;
+ }
+
+ @Override
+ public SelectBuilder fromNamed(Collection<String> graphNames) {
+ datasetHandler.fromNamed(graphNames);
+ return this;
+ }
+
+ @Override
+ public SelectBuilder from(String graphName) {
+ datasetHandler.from(graphName);
+ return this;
+ }
+
+ @Override
+ public SelectBuilder from(Collection<String> graphName) {
+ datasetHandler.from(graphName);
+ return this;
+ }
+
+ @Override
+ public SelectBuilder addOrderBy(String orderBy) {
+ solutionModifier.addOrderBy(orderBy);
+ return this;
+ }
+
+ @Override
+ public SelectBuilder addGroupBy(String groupBy) {
+ solutionModifier.addGroupBy(groupBy);
+ return this;
+ }
+
+ @Override
+ public SolutionModifierHandler getSolutionModifierHandler() {
+ return solutionModifier;
+ }
+
+ @Override
+ public SelectBuilder addHaving(String having) throws ParseException {
+ solutionModifier.addHaving(having);
+ return this;
+ }
+
+ @Override
+ public SelectBuilder setLimit(int limit) {
+ solutionModifier.setLimit(limit);
+ return this;
+ }
+
+ @Override
+ public SelectBuilder setOffset(int offset) {
+ solutionModifier.setOffset(offset);
+ return this;
+ }
+
+ /**
+ * Convert a node to a string.
+ * If the node is a literal return the literal value.
+ * If the node is a URI return the URI enclosed with < and >
+ * If the node is a variable return the name preceeded by '?'
+ * @param node The node to convert.
+ * @return A string representation of the node.
+ */
+ private static String toString(Node node) {
+ if (node.isBlank()) {
+ return node.getBlankNodeLabel();
+ }
+ if (node.isLiteral()) {
+ return node.toString();
+ }
+ if (node.isURI()) {
+ return String.format("<%s>", node.getURI());
+ }
+ if (node.isVariable()) {
+ return String.format("?%s", node.getName());
+ }
+ return node.toString();
+ }
+
+ /**
+ * Convert the object to a string.
+ * If the object is a node or fronts a node then
+ * <ul>
+ * <li>If the node is a literal return the literal value.</li>
+ * <li>If the node is a URI return the URI enclosed with < and ></li>
+ * <li>If the node is a variable return the name preceeded by '?'</li>
+ * </ul>
+ * otherwise return the toString() method of the object.
+ * @param o the Object to convert.
+ * @return The string representation of the object.
+ */
+ public static String makeString(Object o) {
+ if (o instanceof FrontsNode) {
+ return toString(((FrontsNode) o).asNode());
+ }
+ if (o instanceof Node) {
+ return toString((Node) o);
+ }
+ return o.toString();
+ }
+
+ @Override
+ public SelectBuilder addWhere(Triple t) {
+ whereHandler.addWhere(t);
+ return this;
+ }
+
+ @Override
+ public SelectBuilder addWhere(FrontsTriple t) {
+ whereHandler.addWhere(t.asTriple());
+ return this;
+ }
+
+ @Override
+ public SelectBuilder addWhere(Object s, Object p, Object o) {
+ addWhere(new Triple(makeNode(s), makeNode(p), makeNode(o)));
+ return this;
+ }
+
+ @Override
+ public SelectBuilder addOptional(Triple t) {
+ whereHandler.addOptional(t);
+ return this;
+ }
+
+ @Override
+ public SelectBuilder addOptional(FrontsTriple t) {
+ whereHandler.addOptional(t.asTriple());
+ return this;
+ }
+
+ @Override
+ public SelectBuilder addOptional(Object s, Object p, Object o) {
+ addOptional(new Triple(makeNode(s), makeNode(p), makeNode(o)));
+ return this;
+ }
+
+ @Override
+ public SelectBuilder addFilter(String s) throws ParseException {
+ whereHandler.addFilter(s);
+ return this;
+ }
+
+ @Override
+ public SelectBuilder addSubQuery(SelectBuilder subQuery) {
+ prologHandler.addAll(subQuery.prologHandler);
+ whereHandler.addSubQuery(subQuery);
+ return this;
+ }
+
+ @Override
+ public SelectBuilder addUnion(SelectBuilder subQuery) {
+ whereHandler.addUnion(subQuery);
+ return this;
+ }
+
+ @Override
+ public SelectBuilder addGraph(Object graph, SelectBuilder subQuery) {
+ prologHandler.addAll(subQuery.prologHandler);
+ whereHandler.addGraph(makeNode(graph), subQuery.whereHandler);
+ return this;
+ }
+
+ @Override
+ public SelectHandler getSelectHandler() {
+ return selectHandler;
+ }
+
+}
\ No newline at end of file
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/ConstructClause.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/ConstructClause.java
new file mode 100644
index 0000000..285fc92
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/ConstructClause.java
@@ -0,0 +1,74 @@
+/*
+ * 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.clauses;
+
+import org.apache.jena.arq.querybuilder.AbstractQueryBuilder;
+import org.apache.jena.arq.querybuilder.handlers.ConstructHandler;
+
+import com.hp.hpl.jena.graph.FrontsTriple;
+import com.hp.hpl.jena.graph.Triple;
+
+/**
+ * Interface that defines the ConstructClause as per
+ * http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rConstructTemplate
+ *
+ * @param <T>
+ * The Builder type that the clause is part of.
+ */
+public interface ConstructClause<T extends AbstractQueryBuilder<T>> {
+
+ /**
+ * Add a construct triple.
+ *
+ * @param t
+ * The triple to add.
+ * @return The builder for chaining.
+ */
+ public T addConstruct(Triple t);
+
+ /**
+ * Add a construct triple.
+ *
+ * @param t
+ * The triple to add.
+ * @return The builder for chaining.
+ */
+ public T addConstruct(FrontsTriple t);
+
+ /**
+ * Add a construct triple.
+ *
+ * See {@link AbstractQueryBuilder#makeNode} for conversion of the param values.
+ *
+ * @param s
+ * The subject of the triple,
+ * @param p
+ * The predicate of the triple.
+ * @param o
+ * The object of the triple.
+ * @return the builder for chaining.
+ */
+ public T addConstruct(Object s, Object p, Object o);
+
+ /**
+ * Get the Construct handler for this construct clause.
+ * @return the construct handler used by this builder.
+ */
+ public ConstructHandler getConstructHandler();
+
+}
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/DatasetClause.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/DatasetClause.java
new file mode 100644
index 0000000..faa51c0
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/DatasetClause.java
@@ -0,0 +1,75 @@
+/*
+ * 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.clauses;
+
+import java.util.Collection;
+
+import org.apache.jena.arq.querybuilder.AbstractQueryBuilder;
+import org.apache.jena.arq.querybuilder.handlers.DatasetHandler;
+
+/**
+ * Interface that defines the DatasetClause as per
+ * http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rDatasetClause
+ *
+ * @param <T>
+ * The Builder type that the clause is part of.
+ */
+public interface DatasetClause<T extends AbstractQueryBuilder<T>> {
+ /**
+ * Add the "FROM NAMED" graph name.
+ *
+ * @param graphName
+ * the graph name to add.
+ * @return The builder for chaining.
+ */
+ public T fromNamed(String graphName);
+
+ /**
+ * Add several "FROM NAMED" graph names.
+ *
+ * @param graphNames
+ * the collection graph names to add.
+ * @return The builder for chaining.
+ */
+ public T fromNamed(Collection<String> graphNames);
+
+ /**
+ * Add the "FROM" graph name.
+ *
+ * @param graphName
+ * the graph name to add.
+ * @return The builder for chaining.
+ */
+ public T from(String graphName);
+
+ /**
+ * Add several "FROM" graph names.
+ *
+ * @param graphName
+ * the collection graph names to add.
+ * @return The builder for chaining.
+ */
+ public T from(Collection<String> graphName);
+
+ /**
+ * Get the Dataset handler for this clause.
+ * @return The DatasetHandler this clause is using.
+ */
+ public DatasetHandler getDatasetHandler();
+
+}
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/PrologClause.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/PrologClause.java
new file mode 100644
index 0000000..8f69598
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/PrologClause.java
@@ -0,0 +1,105 @@
+/*
+ * 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.clauses;
+
+import java.util.Map;
+
+import org.apache.jena.arq.querybuilder.AbstractQueryBuilder;
+import org.apache.jena.arq.querybuilder.handlers.PrologHandler;
+
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.rdf.model.Resource;
+
+/**
+ * Interface that defines the PrologClause as per
+ * http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rPrologue
+ *
+ * @param <T>
+ * The Builder type that the clause is part of.
+ */
+public interface PrologClause<T extends AbstractQueryBuilder<T>> {
+ /**
+ * Get the prolog handler for this clause.
+ * @return The PrologHandler this clause is using.
+ */
+ public PrologHandler getPrologHandler();
+
+ /**
+ * Add a prefix.
+ *
+ * @param pfx
+ * The prefix.
+ * @param uri
+ * The URI for the prefix
+ * @return The builder for chaining.
+ */
+ public T addPrefix(String pfx, Resource uri);
+
+ /**
+ * Add a prefix.
+ *
+ * @param pfx
+ * The prefix.
+ * @param uri
+ * The URI for the prefix
+ * @return The builder for chaining.
+ */
+ public T addPrefix(String pfx, Node uri);
+
+ /**
+ * Add a prefix.
+ *
+ * @param pfx
+ * The prefix.
+ * @param uri
+ * The URI for the prefix
+ * @return The builder for chaining.
+ */
+ public T addPrefix(String pfx, String uri);
+
+ /**
+ * Add a prefix.
+ *
+ * @param prefixes
+ * A mapping of prefix to URI to add.
+ * @return The builder for chaining.
+ */
+ public T addPrefixes(Map<String, String> prefixes);
+
+ /**
+ * Set the base URI.
+ *
+ * See {@link AbstractQueryBuilder#makeNode} for conversion of the uri param. The resulting Node
+ * must be a URI.
+ *
+ * @param uri
+ * The base URI to use.
+ * @return The builder for chaining.
+ */
+ public T setBase(Object uri);
+
+ /**
+ * Set the base URI.
+ *
+ * @param uri
+ * The base URI to use.
+ * @return The builder for chaining.
+ */
+ public T setBase(String uri);
+
+}
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/SelectClause.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/SelectClause.java
new file mode 100644
index 0000000..2d29010
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/SelectClause.java
@@ -0,0 +1,79 @@
+/*
+ * 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.clauses;
+
+import java.util.List;
+import org.apache.jena.arq.querybuilder.AbstractQueryBuilder;
+import org.apache.jena.arq.querybuilder.handlers.SelectHandler;
+
+import com.hp.hpl.jena.sparql.core.Var;
+
+/**
+ * Interface that defines the SelectClause as per
+ * http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rSelectClause
+ *
+ * @param <T>
+ * The Builder type that the clause is part of.
+ */
+public interface SelectClause<T extends AbstractQueryBuilder<T>> {
+ /**
+ * Get the select handler for this clause
+ * @return The SelectHandler that the clause is using
+ */
+ public SelectHandler getSelectHandler();
+
+ /**
+ * Set set the distinct flag.
+ *
+ * Setting the select distinct will unset reduced if it was set.
+ *
+ * @param state
+ * if true results will be distinct.
+ * @return The builder for chaining.
+ */
+ public T setDistinct(boolean state);
+
+ /**
+ * Set set the reduced flag.
+ *
+ * Setting the select reduced will unset distinct if it was set.
+ *
+ * @param state
+ * if true results will be reduced.
+ * @return The builder for chaining.
+ */
+ public T setReduced(boolean state);
+
+ /**
+ * Add a variable to the select statement.
+ *
+ * A variable may only be added once. Attempting to add the same variable
+ * multiple times will be silently ignored.
+ *
+ * @param var
+ * The variable to add.
+ * @return The builder for chaining.
+ */
+ public T addVar(Object var);
+
+ /**
+ * @return A list of all the variables that have been added.
+ */
+ public List<Var> getVars();
+
+}
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/SolutionModifierClause.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/SolutionModifierClause.java
new file mode 100644
index 0000000..3be18a0
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/SolutionModifierClause.java
@@ -0,0 +1,89 @@
+/*
+ * 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.clauses;
+
+import org.apache.jena.arq.querybuilder.AbstractQueryBuilder;
+import org.apache.jena.arq.querybuilder.handlers.SolutionModifierHandler;
+
+import com.hp.hpl.jena.sparql.lang.sparql_11.ParseException;
+
+/**
+ * Interface that defines the SolutionClause as per
+ * http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rSolutionModifier
+ *
+ * @param <T>
+ * The Builder type that the clause is part of.
+ */
+public interface SolutionModifierClause<T extends AbstractQueryBuilder<T>> {
+
+ /**
+ * Add an order by
+ *
+ * @param orderBy
+ * The variable name to order by.
+ * @return The builder for chaining.
+ */
+ public T addOrderBy(String orderBy);
+
+ /**
+ * Add a group by
+ *
+ * @param groupBy
+ * The variable name to group by.
+ * @return The builder for chaining.
+ */
+ public T addGroupBy(String groupBy);
+
+ /**
+ * Add a having expression.
+ *
+ * @param expression
+ * Expression to evaluate for the having.
+ * @return The builder for chaining.
+ */
+ public T addHaving(String expression) throws ParseException;
+
+ /**
+ * Set the limit.
+ *
+ * Setting the limit to 0 (zero) sets no limit.
+ *
+ * @param limit
+ * the maximum number of results to return.
+ * @return The builder for chaining.
+ */
+ public T setLimit(int limit);
+
+ /**
+ * Set the offset.
+ *
+ * Setting the offset to 0 (zero) sets no offset.
+ *
+ * @param offset
+ * the number of results to skip before returning results..
+ * @return The builder for chaining.
+ */
+ public T setOffset(int offset);
+
+ /**
+ * Get the Solution modifier for this clause.
+ * @return The SolutionModifierHandler the clause is using.
+ */
+ public SolutionModifierHandler getSolutionModifierHandler();
+
+}
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/WhereClause.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/WhereClause.java
new file mode 100644
index 0000000..9f92941
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/WhereClause.java
@@ -0,0 +1,153 @@
+/*
+ * 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.clauses;
+
+import org.apache.jena.arq.querybuilder.AbstractQueryBuilder;
+import org.apache.jena.arq.querybuilder.SelectBuilder;
+import org.apache.jena.arq.querybuilder.handlers.WhereHandler;
+
+import com.hp.hpl.jena.graph.FrontsTriple;
+import com.hp.hpl.jena.graph.Triple;
+import com.hp.hpl.jena.sparql.lang.sparql_11.ParseException;
+
+/**
+ * Interface that defines the WhereClause as per
+ * http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rWhereClause
+ *
+ * @param <T>
+ * The Builder type that the clause is part of.
+ */
+public interface WhereClause<T extends AbstractQueryBuilder<T>> {
+
+ /**
+ * Adds a triple as to the where clause.
+ *
+ * @param t
+ * The triple to add
+ * @return The Builder for chaining.
+ */
+ public T addWhere(Triple t);
+
+ /**
+ * Adds a triple as to the where clause.
+ *
+ * @param t
+ * The triple to add
+ * @return The Builder for chaining.
+ */
+ public T addWhere(FrontsTriple t);
+
+ /**
+ * Adds a triple to the where clause.
+ *
+ * See {@link AbstractQueryBuilder#makeNode} for conversion of the param values.
+ *
+ * @param s
+ * The subject.
+ * @param p
+ * The predicate.
+ * @param o
+ * The object.
+ * @return The Builder for chaining.
+ */
+ public T addWhere(Object s, Object p, Object o);
+
+ /**
+ * Adds an optional triple as to the where clause.
+ *
+ * @param t
+ * The triple to add
+ * @return The Builder for chaining.
+ */
+ public T addOptional(Triple t);
+
+ /**
+ * Adds an optional triple as to the where clause.
+ *
+ * @param t
+ * The triple to add
+ * @return The Builder for chaining.
+ */
+ public T addOptional(FrontsTriple t);
+
+ /**
+ * Adds an optional triple to the where clause.
+ *
+ * See {@link AbstractQueryBuilder#makeNode} for conversion of the param values.
+ *
+ * @param s
+ * The subject.
+ * @param p
+ * The predicate.
+ * @param o
+ * The object.
+ * @return The Builder for chaining.
+ */
+ public T addOptional(Object s, Object p, Object o);
+
+ /**
+ * Adds a filter to the where clause
+ *
+ * @param expression
+ * the expression to evaluate for the filter.
+ * @return @return The Builder for chaining.
+ * @throws ParseException
+ * If the expression can not be parsed.
+ */
+ public T addFilter(String expression) throws ParseException;
+
+ /**
+ * Add a sub query.
+ *
+ * @param subQuery
+ * The subquery as defined by a SelectBuilder.
+ * @return This builder for chaining.
+ */
+ public T addSubQuery(SelectBuilder subQuery);
+
+ /**
+ * Add a union.
+ *
+ * @param union
+ * The union as defined by a SelectBuilder.
+ * @return This builder for chaining.
+ */
+ public T addUnion(SelectBuilder union);
+
+ /**
+ * 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 T addGraph(Object graph, SelectBuilder subQuery);
+
+ /**
+ * Get the Where handler for this clause.
+ * @return The WhereHandler used by this clause.
+ */
+ public WhereHandler getWhereHandler();
+
+}
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/package-info.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/package-info.java
new file mode 100644
index 0000000..e98871a
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * Interfaces that describe various SPARQL clauses as per
+ * http://www.w3.org/TR/2013/REC-sparql11-query-20130321.
+ *
+ * These classes are used to compose consistent interfaces for specific builder implementations.
+ */
+package org.apache.jena.arq.querybuilder.clauses;
\ No newline at end of file
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/ConstructHandler.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/ConstructHandler.java
new file mode 100644
index 0000000..55f1794
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/ConstructHandler.java
@@ -0,0 +1,89 @@
+/*
+ * 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.handlers;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.jena.arq.querybuilder.rewriters.AbstractRewriter;
+
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.Triple;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.sparql.core.BasicPattern;
+import com.hp.hpl.jena.sparql.core.Var;
+import com.hp.hpl.jena.sparql.syntax.Template;
+
+/**
+ * The handler for construct clauses.
+ *
+ */
+public class ConstructHandler implements Handler {
+ private final Query query;
+ private List<Triple> constructs;
+
+ /**
+ * The constructor
+ * @param query The query that this handler will be modifying.
+ */
+ public ConstructHandler(Query query) {
+ this.query = query;
+ constructs = new ArrayList<Triple>();
+ if (query.getConstructTemplate() != null) {
+ for (Triple t : query.getConstructTemplate().getTriples()) {
+ constructs.add(t);
+ }
+ }
+ }
+
+ /**
+ * Add a triple to the construct statement.
+ * @param t The triple to add.
+ */
+ public void addConstruct(Triple t) {
+ constructs.add(t);
+ query.setConstructTemplate(new Template(BasicPattern.wrap(constructs)));
+ }
+
+ /**
+ * Add all the construct handlers from the handler argument to this construct.
+ * @param handler The construct handler to copy from.
+ */
+ public void addAll(ConstructHandler handler) {
+ constructs.addAll(handler.constructs);
+ query.setConstructTemplate(new Template(BasicPattern.wrap(constructs)));
+ }
+
+ @Override
+ public void setVars(Map<Var, Node> values) {
+ if (values.isEmpty()) {
+ return;
+ }
+ AbstractRewriter<Node> rw = new AbstractRewriter<Node>(values) {
+ };
+ query.setConstructTemplate(new Template(BasicPattern.wrap(rw
+ .rewrite(constructs))));
+ }
+
+ @Override
+ public void build() {
+ // there are no special operations for the build.
+ }
+
+}
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/DatasetHandler.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/DatasetHandler.java
new file mode 100644
index 0000000..e829e56
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/DatasetHandler.java
@@ -0,0 +1,149 @@
+/*
+ * 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.handlers;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.sparql.core.Var;
+
+/**
+ * Handler for a dataset.
+ *
+ */
+public class DatasetHandler implements Handler {
+
+ // the query to manage
+ private final Query query;
+
+ /**
+ * Constructor.
+ * @param query The query the handler will manage.
+ */
+ public DatasetHandler(Query query) {
+ this.query = query;
+ }
+
+ /**
+ * Add all the dataset information from the handler argument.
+ * @param datasetHandler The handler to copy from.
+ */
+ public void addAll(DatasetHandler datasetHandler) {
+ from(datasetHandler.query.getGraphURIs());
+ fromNamed(datasetHandler.query.getNamedGraphURIs());
+ }
+
+ /**
+ * Add a graph name to the from named list.
+ * @param graphName The graph name to add.
+ */
+ public void fromNamed(String graphName) {
+ query.addNamedGraphURI(graphName);
+ }
+
+ /**
+ * Add the graph names to the from named list.
+ *
+ * The names are ordered in as defined in the collection.
+ *
+ * @param graphNames The from names to add.
+ */
+ public void fromNamed(Collection<String> graphNames) {
+ for (String uri : graphNames) {
+ query.addNamedGraphURI(uri);
+ }
+ }
+
+ /**
+ * Add the graph names to the from list.
+ * @param graphName the name to add.
+ */
+ public void from(String graphName) {
+ query.addGraphURI(graphName);
+ }
+
+ /**
+ * Add the graph names to the named list.
+ *
+ * The names are ordered in as defined in the collection.
+ *
+ * @param graphNames The names to add.
+ */
+ public void from(Collection<String> graphNames) {
+ for (String uri : graphNames) {
+ query.addGraphURI(uri);
+ }
+ }
+
+ /**
+ * Set the variables for field names that contain lists of strings.
+ *
+ * Strings that start with "?" are assumed to be variable names and will be replaced
+ * with matching node.toString() values.
+ *
+ * @param values The values to set.
+ * @param fieldName The field name in Query that contain a list of strings.
+ */
+ private void setVars(Map<Var, Node> values, String fieldName) {
+ if (values.isEmpty()) {
+ return;
+ }
+ try {
+ Field f = Query.class.getDeclaredField(fieldName);
+ f.setAccessible(true);
+ @SuppressWarnings("unchecked")
+ List<String> orig = (List<String>) f.get(query);
+ List<String> lst = null;
+ if (orig != null) {
+ lst = new ArrayList<String>();
+ for (String s : orig) {
+ Node n = null;
+ if (s.startsWith("?")) {
+ Var v = Var.alloc(s.substring(1));
+ n = values.get(v);
+ }
+ lst.add(n == null ? s : n.toString());
+ }
+ f.set(query, lst);
+ }
+ } catch (NoSuchFieldException e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ } catch (SecurityException e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public void setVars(Map<Var, Node> values) {
+ setVars(values, "namedGraphURIs");
+ setVars(values, "graphURIs");
+ }
+
+ @Override
+ public void build() {
+ // nothing special to do
+ }
+
+}
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/Handler.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/Handler.java
new file mode 100644
index 0000000..a6bf8d5
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/Handler.java
@@ -0,0 +1,42 @@
+/*
+ * 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.handlers;
+
+import java.util.Map;
+
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.sparql.core.Var;
+
+/**
+ * The base interface for handlers.
+ *
+ */
+public interface Handler {
+ /**
+ * Set the values for variables managed by the handler implementation.
+ * This method is called by the builder to set values handled by this Handler implementation.
+ * @param values The map of variable to node value.
+ */
+ public void setVars(Map<Var, Node> values);
+
+ /**
+ * Called by the build process for this handler to perform any adjustments to the query before
+ * the build completes. The adjustments are made after setVars() has been called.
+ */
+ public void build();
+}
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/PrologHandler.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/PrologHandler.java
new file mode 100644
index 0000000..a821e4d
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/PrologHandler.java
@@ -0,0 +1,126 @@
+/*
+ * 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.handlers;
+
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.jena.riot.system.IRIResolver;
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.shared.PrefixMapping;
+import com.hp.hpl.jena.sparql.core.Var;
+
+/**
+ * The proglog handler
+ *
+ */
+public class PrologHandler implements Handler {
+
+ // the query to modify.
+ private final Query query;
+
+ /**
+ * Constructor.
+ * @param query The query to handle.
+ */
+ public PrologHandler(Query query) {
+ this.query = query;
+ }
+
+ /**
+ * get the canonical prefix name.
+ *
+ * Removes ':' from the end of the name if present.
+ *
+ * @param x The prefix name
+ * @return The prefix name with the trialing ':' removed.
+ */
+ private String canonicalPfx(String x) {
+ if (x.endsWith(":"))
+ return x.substring(0, x.length() - 1);
+ return x;
+ }
+
+ /**
+ * Set the base for the query. This is the IRI against which relative names will be resolved.
+ * @param resolver The IRIResolver to set the base from.
+ */
+ public void setBase(IRIResolver resolver) {
+ query.setBaseURI(resolver);
+
+ }
+
+ /**
+ * Set the base for the query. This is the IRI against which relative names will be resolved.
+ * @param base The string to set the base from.
+ */
+ public void setBase(String base) {
+ query.setBaseURI(base);
+ }
+
+ /**
+ * Add a prefix to the prefix mapping.
+ * @param pfx The prefix to add.
+ * @param uri The uri to resolve the prefix to.
+ */
+ public void addPrefix(String pfx, String uri) {
+ query.setPrefix(canonicalPfx(pfx), uri);
+ }
+
+ /**
+ * Add the map of prefixes to the query prefixes.
+ * @param prefixes The map of prefixs to URIs.
+ */
+ public void addPrefixes(Map<String, String> prefixes) {
+ for (Map.Entry<String, String> e : prefixes.entrySet()) {
+ addPrefix(e.getKey(), e.getValue());
+ }
+ }
+
+ /**
+ * Add prefixes from a prefix mapping.
+ * @param prefixes THe prefix mapping to add from.
+ */
+ public void addPrefixes(PrefixMapping prefixes) {
+ query.getPrefixMapping().setNsPrefixes(prefixes);
+ }
+
+ /**
+ * Add the settings from the prolog handler argument.
+ * @param pfxHandler The PrologHandler to read from
+ */
+ public void addAll(PrologHandler pfxHandler) {
+ String val = StringUtils.defaultIfEmpty(pfxHandler.query.getBaseURI(),
+ query.getBaseURI());
+ if (val != null) {
+ setBase(val);
+ }
+ addPrefixes(pfxHandler.query.getPrefixMapping());
+ }
+
+ @Override
+ public void setVars(Map<Var, Node> values) {
+ // nothing to do
+ }
+
+ @Override
+ public void build() {
+ // no special operation to perform
+ }
+}
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/SelectHandler.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/SelectHandler.java
new file mode 100644
index 0000000..70e94a7
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/SelectHandler.java
@@ -0,0 +1,133 @@
+/*
+ * 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.handlers;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Map;
+
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.sparql.core.Var;
+import com.hp.hpl.jena.sparql.core.VarExprList;
+
+/**
+ * A Select clause handler.
+ *
+ */
+public class SelectHandler implements Handler {
+
+ // the query to handle
+ private final Query query;
+
+ /**
+ * Constructor.
+ * @param query The query to manage.
+ */
+ public SelectHandler(Query query) {
+ this.query = query;
+ setDistinct(query.isDistinct());
+ setReduced(query.isReduced());
+ }
+
+ /**
+ * Set the distinct flag.
+ * Set or unset the distinct flag.
+ * Will set the reduced flag if it was previously set.
+ * @param state the state to set the distinct flag to.
+ */
+ public void setDistinct(boolean state) {
+ query.setDistinct(state);
+ if (state) {
+ query.setReduced(false);
+ }
+ }
+
+ /**
+ * Set the reduced flag.
+ * Set or unset the reduced flag.
+ * Will set the reduced flag if it was previously set.
+ * @param state the state to set the reduced flag to.
+ */
+ public void setReduced(boolean state) {
+ query.setReduced(state);
+ if (state) {
+ query.setDistinct(false);
+ }
+ }
+
+ /**
+ * Add a variable to the select.
+ * If the variable is the variables are set to star.
+ * @param var The variable to add.
+ */
+ public void addVar(Var var) {
+ if (var == null) {
+ query.setQueryResultStar(true);
+ } else {
+ query.setQueryResultStar(false);
+ query.addResultVar(var);
+ }
+ }
+
+ /**
+ * Get the list of variables from the query.
+ * @return The list of variables in the query.
+ */
+ public List<Var> getVars() {
+ return query.getProjectVars();
+ }
+
+ /**
+ * Add all the variables from the select handler variable.
+ * @param selectHandler The select handler to copy the variables from.
+ */
+ public void addAll(SelectHandler selectHandler) {
+
+ setReduced(selectHandler.query.isReduced());
+ setDistinct(selectHandler.query.isDistinct());
+ query.setQueryResultStar(selectHandler.query.isQueryResultStar());
+
+ try {
+ Field f = Query.class.getDeclaredField("projectVars");
+ f.setAccessible(true);
+ VarExprList projectVars = (VarExprList) f.get(selectHandler.query);
+ f.set(query, new VarExprList(projectVars));
+ } catch (NoSuchFieldException e) {
+ throw new IllegalStateException(e);
+ } catch (SecurityException e) {
+ throw new IllegalStateException(e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public void setVars(Map<Var, Node> values) {
+ // nothing to do
+ }
+
+ @Override
+ public void build() {
+ if (query.getProject().getVars().isEmpty()) {
+ query.setQueryResultStar(true);
+ }
+ // handle the SELECT * case
+ query.getProjectVars();
+ }
+}
diff --git a/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/SolutionModifierHandler.java b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/SolutionModifierHandler.java
new file mode 100644
index 0000000..50838f5
--- /dev/null
+++ b/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/SolutionModifierHandler.java
@@ -0,0 +1,269 @@
+/*
+ * 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.handlers;
+
+import java.io.ByteArrayInputStream;
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.jena.arq.querybuilder.rewriters.ExprRewriter;
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.query.SortCondition;
+import com.hp.hpl.jena.sparql.core.Var;
+import com.hp.hpl.jena.sparql.core.VarExprList;
+import com.hp.hpl.jena.sparql.expr.Expr;
+import com.hp.hpl.jena.sparql.expr.ExprList;
+import com.hp.hpl.jena.sparql.expr.ExprVar;
+import com.hp.hpl.jena.sparql.lang.sparql_11.ParseException;
+import com.hp.hpl.jena.sparql.lang.sparql_11.SPARQLParser11;
+
+/**
+ * The Solution Modifier handerl.
+ *
+ */
+public class SolutionModifierHandler implements Handler {
+ /**
+ * The order for the ORDER BY modifiers.
+ */
+ public e
<TRUNCATED>