http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/LICENSE
----------------------------------------------------------------------
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.
+

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/README.md
----------------------------------------------------------------------
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> . }`
+

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/license-header.txt
----------------------------------------------------------------------
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

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/pom.xml
----------------------------------------------------------------------
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

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/AbstractQueryBuilder.java
----------------------------------------------------------------------
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;
+       }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/AskBuilder.java
----------------------------------------------------------------------
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

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/ConstructBuilder.java
----------------------------------------------------------------------
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

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/SelectBuilder.java
----------------------------------------------------------------------
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 &lt; and &gt;
+        * 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 &lt; and 
&gt;</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

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/ConstructClause.java
----------------------------------------------------------------------
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();
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/DatasetClause.java
----------------------------------------------------------------------
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();
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/PrologClause.java
----------------------------------------------------------------------
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);
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/SelectClause.java
----------------------------------------------------------------------
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();
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/SolutionModifierClause.java
----------------------------------------------------------------------
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();
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/WhereClause.java
----------------------------------------------------------------------
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();
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/clauses/package-info.java
----------------------------------------------------------------------
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

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/ConstructHandler.java
----------------------------------------------------------------------
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.
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/DatasetHandler.java
----------------------------------------------------------------------
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
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/Handler.java
----------------------------------------------------------------------
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();
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/2fb788d3/jena-extras/jena-querybuilder/src/main/java/org/apache/jena/arq/querybuilder/handlers/PrologHandler.java
----------------------------------------------------------------------
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
+       }
+}

Reply via email to