Author: sallen
Date: Thu Apr  9 02:22:47 2015
New Revision: 1672230

URL: http://svn.apache.org/r1672230
Log:
jena-client - 
1) Big refactor to clean up the code and make changes based on experience using 
the library
2) Use Java 7's AutoClosable
3) Use Jena's underlying update capability that uses Apache HttpClient instead 
of rolling our own 
4) Lots of javadocs 
5) Complete outstanding implementation TODOs 

Added:
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractConnection.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractQueryStatement.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractSparqlStatement.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractUpdateStatement.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractUpdater.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/DatabaseClient.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/DatabaseClientFactory.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateExecution.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/AutoCommitQueryExecution.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphDatabaseClient.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/UpdateEngineUpdater.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpDatabaseClient.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpUpdateExecution.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/SparqlUpdateEntity.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/UpdateWriterUpdater.java
    jena/Experimental/jena-client/src/test/java/org/
    jena/Experimental/jena-client/src/test/java/org/apache/
    jena/Experimental/jena-client/src/test/java/org/apache/jena/
    jena/Experimental/jena-client/src/test/java/org/apache/jena/client/
    jena/Experimental/jena-client/src/test/java/org/apache/jena/client/graph/
    
jena/Experimental/jena-client/src/test/java/org/apache/jena/client/graph/AutoCommitQueryExecutionTest.java
    
jena/Experimental/jena-client/src/test/java/org/apache/jena/client/graph/DatasetGraphTest.java
Removed:
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/ConnectionBase.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/QueryStatementBase.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/Repository.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/RepositoryFactory.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/SparqlStatementBase.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateStatementBase.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdaterBase.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphRepository.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphUpdater.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpRepository.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpUpdater.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/QuadIteratorEntity.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/TripleIteratorEntity.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/UpdateRemote.java
Modified:
    jena/Experimental/jena-client/pom.xml
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/Connection.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/QueryStatement.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/SparqlStatement.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateDeleter.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateInserter.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateQuerier.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateStatementWrapper.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/Updater.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdaterWrapper.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphConnection.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphQueryStatement.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/DatasetGraphUpdateStatement.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpConnection.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpQueryStatement.java
    
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/http/HttpUpdateStatement.java

Modified: jena/Experimental/jena-client/pom.xml
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/pom.xml?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- jena/Experimental/jena-client/pom.xml (original)
+++ jena/Experimental/jena-client/pom.xml Thu Apr  9 02:22:47 2015
@@ -20,7 +20,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.apache.jena</groupId>
   <artifactId>jena-client</artifactId>
-  <version>0.0.14-SNAPSHOT</version>
+  <version>0.0.16-SNAPSHOT</version>
   <name>Apache Jena - Client (SPARQL 1.1 Client API)</name>
   <description>Client is a library that provides an API for querying and 
updating local or remote SPARQL 1.1 endpoints.</description>
   
@@ -56,6 +56,27 @@
       <version>4.9</version>
       <scope>test</scope>
     </dependency>
+    
+    <dependency>
+      <groupId>org.easytesting</groupId>
+      <artifactId>fest-assert</artifactId>
+      <version>1.4</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <version>1.9.5</version>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.hamcrest</groupId>
+          <artifactId>hamcrest-core</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    
   </dependencies>
 
   <distributionManagement>
@@ -79,8 +100,8 @@
           <optimize>true</optimize>
           <debug>true</debug>
           <debuglevel>source,lines,vars</debuglevel>
-          <source>1.6</source>
-          <target>1.6</target>
+          <source>1.7</source>
+          <target>1.7</target>
         </configuration>
       </plugin>
 

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractConnection.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractConnection.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractConnection.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractConnection.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,157 @@
+/*
+ * 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.client;
+
+import org.apache.jena.atlas.iterator.Action ;
+
+import com.hp.hpl.jena.query.ParameterizedSparqlString ;
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.update.Update ;
+
+/**
+ * Abstract class for Connection implementations, provides tracking of 
Query/Update statement creation
+ * that prevents multiple operations from being executed at the same time.
+ */
+public abstract class AbstractConnection implements Connection
+{
+    protected final DatabaseClient databaseClient;
+    
+    protected volatile SparqlStatement operator = null;
+
+    public AbstractConnection(DatabaseClient databaseClient)
+    {
+        if (null == databaseClient) throw new 
IllegalArgumentException("databaseClient must not be null");
+        this.databaseClient = databaseClient;
+    }
+    
+    
+    protected abstract QueryStatement doCreateQueryStatement(Query query);
+    protected abstract QueryStatement doCreateQueryStatement(String 
queryString);
+    
+    protected abstract UpdateStatement doCreateUpdateStatement(Update update);
+    protected abstract UpdateStatement doCreateUpdateStatement(Iterable<? 
extends Update> update);
+    protected abstract UpdateStatement doCreateUpdateStatement(String 
updateString);
+    protected abstract UpdateStatement doCreateUpdateStatement(Action<Updater> 
action);
+    
+    @Override
+    public DatabaseClient getDatabaseClient()
+    {
+        return databaseClient;
+    }
+    
+    protected void checkOperationOngoing()
+    {
+        if (operator != null)
+        {
+            throw new IllegalStateException("You must close any open 
operations before new operations are allowed on this Connection");
+        }
+    }
+
+    @Override
+    public final QueryStatement createQueryStatement(String queryString)
+    {
+        checkOperationOngoing();
+        return registerQueryStatement(doCreateQueryStatement(queryString));
+    }
+    
+    @Override
+    public final QueryStatement createQueryStatement(ParameterizedSparqlString 
paramQuery)
+    {
+        if (null == paramQuery) throw new NullPointerException("paramQuery");
+        return createQueryStatement(paramQuery.toString());
+    }
+    
+    @Override
+    public final QueryStatement createQueryStatement(Query query)
+    {
+        checkOperationOngoing();
+        return registerQueryStatement(doCreateQueryStatement(query));
+    }
+    
+    @Override
+    public final UpdateStatement 
createUpdateStatement(ParameterizedSparqlString paramUpdate)
+    {
+        if (null == paramUpdate) throw new NullPointerException("paramQuery");
+        return createUpdateStatement(paramUpdate.toString());
+    }
+    
+    @Override
+    public final UpdateStatement createUpdateStatement(String updateString)
+    {
+        checkOperationOngoing();
+        return registerUpdateStatement(doCreateUpdateStatement(updateString));
+    }
+    
+    @Override
+    public final UpdateStatement createUpdateStatement(Update update)
+    {
+        checkOperationOngoing();
+        return registerUpdateStatement(doCreateUpdateStatement(update));
+    }
+    
+    @Override
+    public final UpdateStatement createUpdateStatement(Iterable<? extends 
Update> updates)
+    {
+        checkOperationOngoing();
+        return registerUpdateStatement(doCreateUpdateStatement(updates));
+    }
+    
+    @Override
+    public final UpdateStatement createUpdateStatement(Action<Updater> action)
+    {
+        checkOperationOngoing();
+        return registerUpdateStatement(doCreateUpdateStatement(action));
+    }
+    
+    
+    
+    private QueryStatement registerQueryStatement(QueryStatement qs)
+    {
+        QueryStatement toReturn = new QueryStatementWrapper(qs)
+        {
+            @Override public boolean execAsk() { operator = null; return 
super.execAsk(); }
+            @Override public Model execConstruct() { operator = null; return 
super.execConstruct(); }
+            @Override public Model execConstruct(Model m) { operator = null; 
return super.execConstruct(m); }
+            @Override public Model execDescribe() { operator = null; return 
super.execDescribe(); }
+            @Override public Model execDescribe(Model m) { operator = null; 
return super.execDescribe(m); }
+            @Override public void close() { operator = null; super.close(); }
+        };
+        operator = toReturn;
+        return toReturn;
+    }
+    
+    private UpdateStatement registerUpdateStatement(UpdateStatement us)
+    {
+        UpdateStatement toReturn = new UpdateStatementWrapper(us)
+        {
+            @Override public void execUpdate() { super.execUpdate(); operator 
= null; }
+        };
+        operator = toReturn;
+        return toReturn;
+    }
+    
+    @Override
+    public void close()
+    {
+        if (null != operator && operator instanceof QueryStatement)
+        {
+            ((QueryStatement)operator).close();
+        }
+    }
+}

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractQueryStatement.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractQueryStatement.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractQueryStatement.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractQueryStatement.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,174 @@
+/*
+ * 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.client;
+
+import java.util.Iterator;
+
+import com.hp.hpl.jena.graph.Triple;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.query.QueryCancelledException;
+import com.hp.hpl.jena.query.QueryExecution;
+import com.hp.hpl.jena.query.ResultSet;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.ModelFactory;
+import com.hp.hpl.jena.rdf.model.Statement;
+import com.hp.hpl.jena.rdf.model.impl.StmtIteratorImpl;
+import com.hp.hpl.jena.sparql.util.ModelUtils;
+
+public abstract class AbstractQueryStatement<T extends QueryExecution> extends 
AbstractSparqlStatement implements QueryStatement
+{
+    protected final String queryString;
+    protected final Query queryObject;
+    
+    protected boolean cancelRequestedBeforeExecution = false;
+    
+    protected final Object lock = new Object();
+    protected T qe;
+    
+    protected AbstractQueryStatement(String queryString, Connection connection)
+    {
+        super(connection);
+        this.queryString = queryString;
+        this.queryObject = null;
+    }
+    
+    protected AbstractQueryStatement(Query query, Connection connection)
+    {
+        super(connection);
+        this.queryString = null;
+        this.queryObject = query;
+    }
+
+    @Override
+    public void close()
+    {
+        if (null != qe) {
+            qe.close();
+        }
+    }
+    
+    protected void doCancel()
+    {
+        if (null != qe) {
+            qe.abort();
+        }
+    }
+    
+    protected abstract T createQueryExecution();
+    
+    protected void createAndSetQueryExecution()
+    {
+        T qe = createQueryExecution();
+        qe.setTimeout(timeout1, timeout2);
+        
+        synchronized(lock)
+        {
+            if (null != this.qe)
+            {
+                throw new IllegalStateException("QueryStatement objects may 
only be used once");
+            }
+            
+            if (cancelRequestedBeforeExecution)
+            {
+                throw new QueryCancelledException();
+            }
+            this.qe = qe;
+        }
+    }
+
+    @Override
+    public void cancel()
+    {
+        synchronized (lock)
+        {
+            if (null != qe)
+            {
+                doCancel();
+            }
+            else
+            {
+                cancelRequestedBeforeExecution = true;
+            }
+        }
+    }
+    
+    @Override
+    public ResultSet execSelect()
+    {
+        createAndSetQueryExecution();
+        return qe.execSelect();
+    }
+    
+    @Override
+    public Iterator<Triple> execConstructTriples()
+    {
+        createAndSetQueryExecution();
+        return qe.execConstructTriples();
+    }
+
+    @Override
+    public Iterator<Triple> execDescribeTriples()
+    {
+        createAndSetQueryExecution();
+        return qe.execDescribeTriples();
+    }
+
+    @Override
+    public boolean execAsk()
+    {
+        createAndSetQueryExecution();
+        return qe.execAsk();
+    }
+
+
+    @Override
+    public Model execConstruct()
+    {
+        return execConstruct(ModelFactory.createDefaultModel());
+    }
+
+    @Override
+    public Model execConstruct(Model model)
+    {
+        return model.add(new StmtIteratorImpl(execConstructStatements(model)));
+    }
+    
+    @Override
+    public Iterator<Statement> execConstructStatements(final Model refModel)
+    {
+        return ModelUtils.triplesToStatements(execConstructTriples(), 
refModel);
+    }
+
+    @Override
+    public Model execDescribe()
+    {
+        return execDescribe(ModelFactory.createDefaultModel());
+    }
+
+    @Override
+    public Model execDescribe(Model model)
+    {
+        return model.add(new StmtIteratorImpl(execDescribeStatements(model)));
+    }
+    
+    @Override
+    public Iterator<Statement> execDescribeStatements(final Model refModel)
+    {
+        return ModelUtils.triplesToStatements(execDescribeTriples(), refModel);
+    }
+}

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractSparqlStatement.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractSparqlStatement.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractSparqlStatement.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractSparqlStatement.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,70 @@
+/*
+ * 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.client;
+
+import java.util.concurrent.TimeUnit;
+
+abstract class AbstractSparqlStatement implements SparqlStatement
+{
+
+    protected final Connection connection;
+    protected long timeout1 = -1;
+    protected long timeout2 = -1;
+    
+    
+    protected AbstractSparqlStatement(Connection connection)
+    {
+        this.connection = connection;
+    }
+    
+    @Override
+    public Connection getConnection()
+    {
+        return connection;
+    }
+
+    @Override
+    public void setTimeout(long timeout)
+    {
+        setTimeout(timeout, TimeUnit.MILLISECONDS);
+    }
+
+    @Override
+    public void setTimeout(long timeout, TimeUnit timeoutUnits)
+    {
+        setTimeout(timeout, timeoutUnits, 0, TimeUnit.MILLISECONDS);
+    }
+
+    @Override
+    public void setTimeout(long timeout1, long timeout2)
+    {
+        setTimeout(timeout1, TimeUnit.MILLISECONDS, timeout2, 
TimeUnit.MILLISECONDS);
+    }
+
+    @Override
+    public void setTimeout(long timeout1, TimeUnit timeUnit1, long timeout2, 
TimeUnit timeUnit2)
+    {
+        timeout1 = asMillis(timeout1, timeUnit1);
+        timeout2 = asMillis(timeout2, timeUnit2);
+    }
+
+    private static long asMillis(long duration, TimeUnit timeUnit)
+    {
+        return (duration < 0 ) ? duration : timeUnit.toMillis(duration) ;
+    }
+}
\ No newline at end of file

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractUpdateStatement.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractUpdateStatement.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractUpdateStatement.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractUpdateStatement.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,72 @@
+/*
+ * 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.client;
+
+import java.util.Arrays ;
+
+import org.apache.jena.atlas.iterator.Action ;
+
+import com.hp.hpl.jena.update.Update ;
+
+
+public abstract class AbstractUpdateStatement extends AbstractSparqlStatement 
implements UpdateStatement
+{
+    protected final Action<Updater> action;
+    
+    public AbstractUpdateStatement(final String updateString, final Connection 
connection)
+    {
+        this(new Action<Updater>() {
+            @Override
+            public void apply(Updater updater)
+            {
+                updater.update(updateString);
+            }
+        }, connection);
+    }
+    
+    public AbstractUpdateStatement(Update update, Connection connection)
+    {
+        this(Arrays.asList(update), connection);
+    }
+    
+    public AbstractUpdateStatement(final Iterable<? extends Update> updates, 
final Connection connection)
+    {
+        this(new Action<Updater>() {
+            @Override
+            public void apply(Updater updater)
+            {
+                updater.update(updates);
+            }
+        }, connection);
+    }
+    
+    public AbstractUpdateStatement(final Action<Updater> action, final 
Connection connection)
+    {
+        super(connection);
+        this.action = action;
+    }
+    
+    
+    protected abstract UpdateExecution createUpdateExecution(); 
+    
+    @Override
+    public void execUpdate()
+    {
+        createUpdateExecution().execUpdate(action);
+    }
+}

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractUpdater.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractUpdater.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractUpdater.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/AbstractUpdater.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,367 @@
+/**
+ * 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.client;
+
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.apache.jena.atlas.iterator.Iter;
+import org.apache.jena.atlas.iterator.Transform;
+import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.RDFLanguages ;
+import org.apache.jena.riot.RiotReader;
+
+import com.hp.hpl.jena.graph.Graph;
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.Triple;
+import com.hp.hpl.jena.query.ParameterizedSparqlString;
+import com.hp.hpl.jena.sparql.core.DatasetGraph;
+import com.hp.hpl.jena.sparql.core.Quad;
+import com.hp.hpl.jena.update.Update;
+import com.hp.hpl.jena.update.UpdateFactory;
+
+/**
+ * An abstract implementation of Updater that handles all of the convenience 
methods,
+ * and only requires subclasses to implement three methods:
+ * {@link #doInsert(Iterator)}, {@link #doDelete(Iterator)}, and {@link 
#doUpdate(Iterator)}
+ */
+public abstract class AbstractUpdater implements Updater
+{
+    protected abstract void doInsert(Iterator<? extends Quad> quadIter);
+    protected abstract void doDelete(Iterator<? extends Quad> quadIter);
+    protected abstract void doUpdate(Iterator<? extends Update> updateIter);
+    
+    // -- Querier -----------------------
+    
+    @Override
+    public void update(Iterator<? extends Update> updateIter)
+    {
+        doUpdate(updateIter);
+    }
+    
+    @Override
+    public void update(Iterable<? extends Update> updates)
+    {
+        update(updates.iterator());
+    }
+    
+    @Override
+    public void update(String updateQuery)
+    {
+        update(UpdateFactory.create(updateQuery));
+    }
+    
+    @Override
+    public void update(ParameterizedSparqlString paramUpdateString)
+    {
+        if (null == paramUpdateString) throw new 
NullPointerException("paramUpdateString");
+        update(UpdateFactory.create(paramUpdateString.toString()));
+    }
+    
+    @Override
+    public void update(String updateQuery, String baseURI)
+    {
+        update(UpdateFactory.create(updateQuery, baseURI));
+    }
+    
+    @Override
+    public void update(Update update)
+    {
+        update(Arrays.asList(update));
+    }
+    
+    // -- Inserter ----------------------
+    
+    @Override
+    public void insert(Iterator<? extends Quad> quadIter)
+    {
+        doInsert(quadIter);
+    }
+    
+    @Override
+    public void insert(Quad q)
+    {
+        insert(Arrays.asList(q));
+    }
+
+    @Override
+    public void insert(Node graphName, Triple t)
+    {
+        if (null == graphName) graphName = Quad.defaultGraphIRI;
+        insert(Quad.create(graphName, t));
+    }
+
+    @Override
+    public void insert(Iterable<? extends Quad> quads)
+    {
+        insert(quads.iterator());
+    }
+
+    @Override
+    public void insert(DatasetGraph dsg)
+    {
+        insert(dsg.find());
+    }
+    
+    @Override
+    public void insert(Triple t)
+    {
+        insert(null, t);
+    }
+
+    @Override
+    public void insert(Node graphName, Graph g)
+    {
+        insert(graphName, g.find(null, null, null));
+    }
+    
+    @Override
+    public void insert(Node graphName, Iterable<? extends Triple> triples)
+    {
+        insert(graphName, triples.iterator());
+    }
+    
+    @Override
+    public void insert(final Node graphName, Iterator<? extends Triple> 
tripleIter)
+    {
+        insert(Iter.map(tripleIter, new Transform<Triple, Quad>()
+        {
+            @Override
+            public Quad convert(Triple item)
+            {
+                return Quad.create(graphName, item);
+            }
+        }));
+    }
+    
+    @Override
+    public void insert(InputStream in, Lang lang)
+    {
+        insert(in, lang, null);
+    }
+
+    @Override
+    public void insert(InputStream in, Lang lang, String base)
+    {
+        if (!RDFLanguages.isQuads(lang))
+        {
+            throw new IllegalArgumentException("lang must be a Quad language, 
or you must call the insert() method with a graph name for Triple languages");
+        }
+        
+        Iterator<Quad> it = RiotReader.createIteratorQuads(in, lang, base);
+        try
+        {
+            insert(it);
+        }
+        finally
+        {
+            Iter.close(it);
+        }
+    }
+
+    @Override
+    public void insert(Node graphName, InputStream in, Lang lang)
+    {
+        insert(graphName, in, lang, null);
+    }
+
+    @Override
+    public void insert(final Node graphName, InputStream in, Lang lang, String 
base)
+    {
+        Iterator<Quad> it;
+        if (RDFLanguages.isTriples(lang))
+        {
+            Iterator<Triple> parser = RiotReader.createIteratorTriples(in, 
lang, base);
+            
+            it = Iter.map(parser, new Transform<Triple, Quad>()
+            {
+                @Override
+                public Quad convert(Triple item)
+                {
+                    return Quad.create(graphName, item);
+                }
+            });
+        }
+        else
+        {
+            // We'll allow Quad languages, and ignore the graph specified in 
the inputstream in favor of the provided one
+            
+            Iterator<Quad> parser = RiotReader.createIteratorQuads(in, lang, 
base);
+            
+            it = Iter.map(parser, new Transform<Quad, Quad>()
+            {
+                @Override
+                public Quad convert(Quad item)
+                {
+                    return Quad.create(graphName, item.getSubject(), 
item.getPredicate(), item.getObject());
+                }
+            });
+        }
+        
+        try
+        {
+            insert(it);
+        }
+        finally
+        {
+            Iter.close(it);
+        }
+    }
+
+    
+    
+    // -- Deleter -----------------
+    
+    @Override
+    public void delete(Iterator<? extends Quad> quadIter)
+    {
+        doDelete(quadIter);
+    }
+    
+    @Override
+    public void delete(Quad q)
+    {
+        delete(Arrays.asList(q));
+    }
+    
+    @Override
+    public void delete(Node graphName, Triple t)
+    {
+        if (null == graphName) graphName = Quad.defaultGraphIRI;
+        delete(Quad.create(graphName, t));
+    }
+
+    @Override
+    public void delete(Iterable<? extends Quad> quads)
+    {
+        delete(quads.iterator());
+    }
+
+    @Override
+    public void delete(DatasetGraph dsg)
+    {
+        delete(dsg.find());
+    }
+    
+    public void delete(Triple t)
+    {
+        delete(null, t);
+    }
+
+    @Override
+    public void delete(Node graphName, Graph g)
+    {
+        delete(graphName, g.find(null, null, null));
+    }
+    
+    @Override
+    public void delete(Node graphName, Iterable<? extends Triple> triples)
+    {
+        delete(graphName, triples.iterator());
+    }
+    
+    @Override
+    public void delete(final Node graphName, Iterator<? extends Triple> 
tripleIter)
+    {
+        delete(Iter.map(tripleIter, new Transform<Triple, Quad>()
+        {
+            @Override
+            public Quad convert(Triple item)
+            {
+                return Quad.create(graphName, item);
+            }
+        }));
+    }
+    
+    @Override
+    public void delete(InputStream in, Lang lang)
+    {
+        delete(in, lang, null);
+    }
+
+    @Override
+    public void delete(InputStream in, Lang lang, String base)
+    {
+        if (!RDFLanguages.isQuads(lang))
+        {
+            throw new IllegalArgumentException("lang must be a Quad language, 
or you must call the delete() method with a graph name for Triple languages");
+        }
+        
+        Iterator<Quad> it = RiotReader.createIteratorQuads(in, lang, base);
+        try
+        {
+            delete(it);
+        }
+        finally
+        {
+            Iter.close(it);
+        }
+    }
+
+    @Override
+    public void delete(Node graphName, InputStream in, Lang lang)
+    {
+        delete(graphName, in, lang, null);
+    }
+
+    @Override
+    public void delete(final Node graphName, InputStream in, Lang lang, String 
base)
+    {
+        Iterator<Quad> it;
+        if (RDFLanguages.isTriples(lang))
+        {
+            Iterator<Triple> parser = RiotReader.createIteratorTriples(in, 
lang, base);
+            
+            it = Iter.map(parser, new Transform<Triple, Quad>()
+            {
+                @Override
+                public Quad convert(Triple item)
+                {
+                    return Quad.create(graphName, item);
+                }
+            });
+        }
+        else
+        {
+            // We'll allow Quad languages, and ignore the graph specified in 
the inputstream in favor of the provided one
+            
+            Iterator<Quad> parser = RiotReader.createIteratorQuads(in, lang, 
base);
+            
+            it = Iter.map(parser, new Transform<Quad, Quad>()
+            {
+                @Override
+                public Quad convert(Quad item)
+                {
+                    return Quad.create(graphName, item.getSubject(), 
item.getPredicate(), item.getObject());
+                }
+            });
+        }
+        
+        try
+        {
+            delete(it);
+        }
+        finally
+        {
+            Iter.close(it);
+        }
+    }
+}
+

Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/Connection.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/Connection.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/Connection.java
 (original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/Connection.java
 Thu Apr  9 02:22:47 2015
@@ -18,29 +18,35 @@
 
 package org.apache.jena.client;
 
-import org.apache.jena.atlas.lib.Closeable;
+import org.apache.jena.atlas.iterator.Action ;
 
-import com.hp.hpl.jena.query.ParameterizedSparqlString;
-import com.hp.hpl.jena.query.Query;
-import com.hp.hpl.jena.sparql.core.Transactional;
-import com.hp.hpl.jena.update.Update;
+import com.hp.hpl.jena.query.ParameterizedSparqlString ;
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.sparql.core.Transactional ;
+import com.hp.hpl.jena.update.Update ;
 
 /**
- * A connection (session) with a specific repository.  SPARQL statements are 
executed and results returned within the context of a connection.
+ * A connection (session) with a specific database.  SPARQL statements are 
executed and results returned within the context of a connection.
+ * <p>
+ * Transactions can be controlled manually with {@link #begin()}/{@link 
#commit()}/{@link #abort()}/{@link #end()} or they can be controlled
+ * automatically in auto commit mode, in which each query or update is an 
individual transaction.
  */
-public interface Connection extends Transactional, Closeable
+public interface Connection extends Transactional, AutoCloseable
 {
-    
-//    void isAutoCommit();
-//    void setAutoCommit(boolean autoCommit);
-    
-//    Service getServices();
+    /**
+     * Closes the connection.  It is important to close query connection 
objects in order to release resources.
+     * If a transaction is a write transaction, is in-progress, and has not 
been committed, then this call will
+     * rollback the transaction. Best practice is to use a connection object 
inside of a try-with-resources block,
+     * which will call this close() method automatically.
+     */
+    @Override
+    void close();
     
     /**
-     * Retrieves the {@link Repository} object that produced this 
<code>Connection</code> object.
-     * @return the repository that produced this connection
+     * Retrieves the {@link DatabaseClient} object that produced this 
<code>Connection</code> object.
+     * @return the database client that produced this connection
      */
-    Repository getRepository();
+    DatabaseClient getDatabaseClient();
     
     /**
      * Answers whether the {@link Connection} supports Transactions.  If it 
does then the {@link Transactional} methods
@@ -77,20 +83,64 @@ public interface Connection extends Tran
      */
     QueryStatement createQueryStatement(ParameterizedSparqlString 
paramQueryString);
     
+    /**
+     * Create an UpdateStatement for the supplied SPARQL update object.  
Execution of
+     * the update is not performed until {@link UpdateStatement#execUpdate()} 
is called.
+     * 
+     * @param update the SPARQL update object to initialize the 
UpdateStatement with
+     * @return an UpdateStatement based on the supplied update query object
+     */
     UpdateStatement createUpdateStatement(Update update);
+    
+    /**
+     * Create an UpdateStatement for the supplied SPARQL update objects.  
Execution of
+     * the update is not performed until {@link UpdateStatement#execUpdate()} 
is called.
+     * All update queries in the Iterable will be executed atomically in a 
single update
+     * statement.
+     * 
+     * @param updates an Iterable containing SPARQL update object to 
initialize the UpdateStatement with
+     * @return an UpdateStatement based on the supplied update query objects
+     */
     UpdateStatement createUpdateStatement(Iterable<? extends Update> updates);
+    
+    /**
+     * Create an UpdateStatement for the supplied SPARQL update query string.  
Execution of
+     * the update is not performed until {@link UpdateStatement#execUpdate()} 
is called.
+     * 
+     * @param update the SPARQL update query string to initialize the 
UpdateStatement with
+     * @return an UpdateStatement based on the supplied update query string
+     */
     UpdateStatement createUpdateStatement(String updateString);
+    
+    /**
+     * Create an UpdateStatement for the supplied SPARQL update {@link 
ParameterizedSparqlString}.  Execution of
+     * the update is not performed until {@link UpdateStatement#execUpdate()} 
is called.
+     * 
+     * @param update the SPARQL update ParameterizedSparqlString to initialize 
the UpdateStatement with
+     * @return an UpdateStatement based on the supplied update query 
ParameterizedSparqlString
+     */
     UpdateStatement createUpdateStatement(ParameterizedSparqlString 
paramUpdateString);
     
-
-    Updater createStreamingUpdater();
+    /**
+     * Create an UpdateStatement for the supplied SPARQL update action.  
Execution of
+     * the update is not performed until {@link UpdateStatement#execUpdate()} 
is called.
+     * <p>
+     * This method will stream the supplied updates to the database.  This 
will allow for
+     * large updates that would not otherwise fit into memory.  It also allows 
streaming
+     * RDF files and Models to the database as well.
+     * 
+     * @param action an {@link Action} that will apply updates to a suppled 
{@link Updater} object;
+     *               these updates are streamed into the database
+     * @return an UpdateStatement based on the supplied <code>{@literal 
Action<Updater>}</code>
+     */
+    UpdateStatement createUpdateStatement(Action<Updater> action);
     
+
     // I think we'll not expose these...  The original idea was to better 
support the
     // SPARQL Graph Store Protocol, which would not allow mixing these 
operations into a
     // single atomic operation.  But I feel this is too complicated for now, 
and will
     // instead assume that we have a full SPARQL 1.1 Update endpoint to work 
against.
-//    UpdateInserter createBulkUpdateInserter();
-//    UpdateDeleter createBulkUpdateDeleter();
-//    UpdateQuerier createBulkUpdateQuerier();
+//    UpdateStatement createBulkUpdateInserter(Action<UpdateInserter> action);
+//    UpdateStatement createBulkUpdateDeleter(Action<UpdateDeleter> action);
 }
 

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/DatabaseClient.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/DatabaseClient.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/DatabaseClient.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/DatabaseClient.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,71 @@
+/**
+ * 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.client;
+
+
+/**
+ * Represents a client of an RDF database.  This can be local or remote.  
{@link DatabaseClient} instances are typically retrieved
+ * from {@link DatabaseClientFactory}.
+ * <p>
+ * Example usage:
+ * <code>
+ * <pre>
+ * DatabaseClient client = 
DatabaseClientFactory.createLocal(TDBFactory.createDatasetGraph());
+ * try(Connection conn = client.getConnection())
+ * {
+ *     conn.begin(ReadWrite.WRITE);
+ *     try
+ *     {
+ *         UpdateStatement us = conn.createUpdateStatement("prefix : 
&lt;http://example.org/&gt;\n insert data { :x :y :z }");
+ *         us.execUpdate();
+ *         conn.commit();
+ *     }
+ *     finally
+ *     {
+ *         conn.end();
+ *     }
+ *     
+ *     // Print out the contents of the database using an AutoCommit 
transaction
+ *     try (QueryStatement qs = conn.createQueryStatement("select * where { ?s 
?p ?o }"))
+ *     {
+ *         ResultSetFormatter.out(System.out, qs.execSelect());
+ *     }
+ * }
+ * 
+ * // Output:
+ * // 
----------------------------------------------------------------------------
+ * // | s                      | p                      | o                    
  |
+ * // 
============================================================================
+ * // | &lt;http://example.org/x&gt; | &lt;http://example.org/y&gt; | 
&lt;http://example.org/z&gt; |
+ * // 
----------------------------------------------------------------------------
+ * </pre>
+ * </code>
+ */
+public interface DatabaseClient
+{
+    // A limit on the number of connections?  I guess based on the underlying 
implementation.  HTTP usually has a limit.
+    /**
+     * Creates and returns a new Connection to this database.
+     * 
+     * @return a new Connection to this database
+     */
+    Connection getConnection();
+    
+}
+

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/DatabaseClientFactory.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/DatabaseClientFactory.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/DatabaseClientFactory.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/DatabaseClientFactory.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,141 @@
+/*
+ * 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.client;
+
+import org.apache.jena.atlas.web.auth.HttpAuthenticator ;
+import org.apache.jena.client.graph.DatasetGraphDatabaseClient ;
+import org.apache.jena.client.http.HttpDatabaseClient ;
+
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.Transactional ;
+
+/**
+ * A factory for local and remote (SPARQL 1.1 Protocol) DatabaseClients.
+ */
+public class DatabaseClientFactory
+{
+    /**
+     * Creates a database client around a local DatasetGraph.  If the dataset 
implements the Transactional interface, transactions will be performed.
+     * 
+     * @param dsg the local database
+     * @return a DatabaseClient for the supplied database
+     */
+    public static DatasetGraphDatabaseClient createLocal(final DatasetGraph 
dsg)
+    {
+        return createLocal(dsg, (dsg instanceof Transactional) ? 
(Transactional)dsg : null);
+    }
+    
+    /**
+     * Creates a database client around a local DatasetGraph using the 
specified Transactional object.
+     * Note that all transaction control should be performed through the 
Connection objects
+     * returned by this DatabaseClient and not on the Transactional object.
+     * 
+     * @param dsg the local database
+     * @param tx the Transactional object to use for transactions; or null if 
no transactions desired
+     * @return a DatabaseClient for the supplied database
+     */
+    public static DatasetGraphDatabaseClient createLocal(final DatasetGraph 
dsg, final Transactional tx)
+    {
+        return new DatasetGraphDatabaseClient(dsg, tx);
+    }
+    
+    /**
+     * Creates a database client around a remote SPARQL HTTP-compliant 
database with no authentication.
+     * <p>
+     * <strong>Note:</strong> Databases other than Jena Fuseki may be severely 
limited on the type and size
+     * of SPARQL 1.1 Update queries.  For example, Sesame (and Sesame-based 
endpoints) have two main limitations:
+     * <ol>
+     *   <li>
+     *     Sesame only supports the {@code 
"application/x-www-form-urlencoded"} content-type.  By default DatabaseClient
+     *     will use the {@code "application/sparql-update"} content-type, but 
it can be changed to use 
+     *     {@code "application/x-www-form-urlencoded"} by setting the 
appropriate type on the {@link HttpDatabaseClient} object.
+     *     <code>
+     *     <pre>
+     * HttpDatabaseClient client = 
DatabaseClientFactory.createRemote(queryEndpoint, updateEndpoint);
+     * client.setUpdateContentType(WebContent.contentTypeHTMLForm);</pre>
+     *     </code>
+     *     <strong>Warning:</strong> When 
<code>"application/x-www-form-urlencoded"</code> is used then the update 
request will not be
+     *     streaming and will be buffered entirely into memory before being 
submitted to the server.
+     *   </li>
+     *   <p><br>
+     *   <li>
+     *     Sesame parses SPARQL Update request into an in-memory Abstract 
Syntax Tree (AST) completely before executing the
+     *     query.  This can cause two issues: 1) an update request with a 
large number of operations may cause a an OutOfMemoryException;
+     *     and 2) INSERT DATA and DELETE DATA operations are not streamed into 
the underlying repository, and large such operations
+     *     may cause either an OutOfMemoryException or a 
StackOverflowException.
+     *     <p><br>
+     *     <strong>Note:</strong> Sesame may not actually report the true 
exception, rather it seems to report
+     *     {@code org.openrdf.http.server.ClientHTTPException: Unsupported 
MIME type: application/x-www-form-urlencoded} when
+     *     a large update requst is submitted.
+     *     <p><br>
+     *     The work-around for this issue is to break your update query into 
smaller chunks and submit them as separate update requests.
+     *   </li>
+     * </ol>
+     * 
+     * @param queryEndpoint the SPARQL query endpoint URL; if null, then you 
may not execute queries against the endpoint
+     * @param updateEndpoint the SPARQL update endpoint URL; if null, then you 
may not execute updates against the endpoint
+     * @return a DatabaseClient for the supplied database
+     */
+    public static HttpDatabaseClient createRemote(final String queryEndpoint, 
final String updateEndpoint)
+    {
+        return createRemote(queryEndpoint, updateEndpoint, null);
+    }
+    
+    /**
+     * Creates a database client around a remote SPARQL HTTP-compliant 
database.
+     * <p>
+     * <strong>Note:</strong> Databases other than Jena Fuseki may be severely 
limited on the type and size
+     * of SPARQL 1.1 Update queries.  For example, Sesame (and Sesame-based 
endpoints) have two main limitations:
+     * <ol>
+     *   <li>
+     *     Sesame only supports the {@code 
"application/x-www-form-urlencoded"} content-type.  By default DatabaseClient
+     *     will use the {@code "application/sparql-update"} content-type, but 
it can be changed to use 
+     *     {@code "application/x-www-form-urlencoded"} by setting the 
appropriate type on the {@link HttpDatabaseClient} object.
+     *     <code>
+     *     <pre>
+     * HttpDatabaseClient client = 
DatabaseClientFactory.createRemote(queryEndpoint, updateEndpoint);
+     * client.setUpdateContentType(WebContent.contentTypeHTMLForm);</pre>
+     *     </code>
+     *     <strong>Warning:</strong> When 
<code>"application/x-www-form-urlencoded"</code> is used then the update 
request will not be
+     *     streaming and will be buffered entirely into memory before being 
submitted to the server.
+     *   </li>
+     *   <p><br>
+     *   <li>
+     *     Sesame parses SPARQL Update request into an in-memory Abstract 
Syntax Tree (AST) completely before executing the
+     *     query.  This can cause two issues: 1) an update request with a 
large number of operations may cause a an OutOfMemoryException;
+     *     and 2) INSERT DATA and DELETE DATA operations are not streamed into 
the underlying repository, and large such operations
+     *     may cause either an OutOfMemoryException or a 
StackOverflowException.
+     *     <p><br>
+     *     <strong>Note:</strong> Sesame may not actually report the true 
exception, rather it seems to report
+     *     {@code org.openrdf.http.server.ClientHTTPException: Unsupported 
MIME type: application/x-www-form-urlencoded} when
+     *     a large update requst is submitted.
+     *     <p><br>
+     *     The work-around for this issue is to break your update query into 
smaller chunks and submit them as separate update requests.
+     *   </li>
+     * </ol>
+     * 
+     * @param queryEndpoint the SPARQL query endpoint URL; if null, then you 
may not execute queries against the endpoint
+     * @param updateEndpoint the SPARQL update endpoint URL; if null, then you 
may not execute updates against the endpoint
+     * @param authenticator the HTTP authenticator to use; if null, then no 
authenticator is used
+     * @return a DatabaseClient for the supplied database
+     */
+    public static HttpDatabaseClient createRemote(final String queryEndpoint, 
final String updateEndpoint, final HttpAuthenticator authenticator)
+    {
+        return new HttpDatabaseClient(queryEndpoint, updateEndpoint, 
authenticator);
+    }
+}

Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/QueryStatement.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/QueryStatement.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/QueryStatement.java
 (original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/QueryStatement.java
 Thu Apr  9 02:22:47 2015
@@ -36,7 +36,7 @@ import com.hp.hpl.jena.rdf.model.Stateme
  * @see Connection#createQueryStatement
  * @see ResultSet
  */
-public interface QueryStatement extends SparqlStatement
+public interface QueryStatement extends SparqlStatement, AutoCloseable
 {
     /**
      * Execute an ASK query.
@@ -126,4 +126,19 @@ public interface QueryStatement extends
      * by executing the DESCRIBE query.
      */
     Iterator<Triple> execDescribeTriples();
+    
+    /**
+     *  Close the query statement and stop query evaluation as soon as 
convenient.  QueryStatement objects,
+     *  {@link ResultSet}s from {@link #execSelect}, and 
<code>Iterator&lt;Triple></code>s from
+     *  {@link #execConstructTriples()} or {@link #execDescribeTriples()}, can 
not be used once the
+     *  QueryStatment is closed.  Model results from {@link #execConstruct} 
and {@link #execDescribe} are
+     *  still valid.
+     *  <p>
+     *  It is important to close query statement objects in order to release 
resources such as working memory
+     *  and to stop the query execution.  Some storage subsystems require 
explicit ends of operations and this
+     *  operation will cause those to be called where necessary. No operations 
on the query statement or any
+     *  associated result set are permitted after this call.
+     */
+    @Override
+    void close();
 }

Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/SparqlStatement.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/SparqlStatement.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/SparqlStatement.java
 (original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/SparqlStatement.java
 Thu Apr  9 02:22:47 2015
@@ -17,11 +17,9 @@
  */
 package org.apache.jena.client;
 
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeUnit ;
 
-import org.apache.jena.atlas.lib.Closeable;
-
-public interface SparqlStatement extends Closeable
+public interface SparqlStatement
 {
 
     /**
@@ -31,15 +29,6 @@ public interface SparqlStatement extends
     public Connection getConnection();
 
     /**
-     * Releases this Statement's resources immediately instead of waiting for 
this to happen when it is
-     * automatically closed. It is generally good practice to release 
resources as soon as you are finished
-     * with them to avoid tying up database resources.  Calling the method 
close on a Statement object that
-     * is already closed has no effect.
-     */
-    @Override
-    public void close();
-    
-    /**
      * Cancels this <code>SparqlStatement</code> object mid-execution if the 
implementation supports it.
      * This method can be called by a different thread than is currently 
executing the query.  There
      * is no guarantee that the concrete implementation actually will stop or 
that it will do so immediately.

Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateDeleter.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateDeleter.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateDeleter.java
 (original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateDeleter.java
 Thu Apr  9 02:22:47 2015
@@ -18,35 +18,129 @@
 
 package org.apache.jena.client;
 
-import java.io.InputStream;
-import java.util.Iterator;
+import java.io.InputStream ;
+import java.util.Iterator ;
 
-import org.apache.jena.atlas.lib.Closeable;
-import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.Lang ;
 
-import com.hp.hpl.jena.graph.Graph;
-import com.hp.hpl.jena.graph.Node;
-import com.hp.hpl.jena.graph.Triple;
-import com.hp.hpl.jena.sparql.core.DatasetGraph;
-import com.hp.hpl.jena.sparql.core.Quad;
-
-public interface UpdateDeleter extends Closeable
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+
+/**
+ * Represents a streamable SPARQL Update DELETE DATA operation. 
+ */
+public interface UpdateDeleter
 {
-    // Quads
-    void delete(Quad q);
-    void delete(Iterable<? extends Quad> quads);
-    void delete(Iterator<? extends Quad> quadIter);
-    void delete(DatasetGraph dsg);
-    void delete(InputStream in, Lang lang);  // Lang must be NQUADS or TRIG
-    void delete(InputStream in, Lang lang, String base);  // Lang must be 
NQUADS or TRIG
-    
     // Triples
+    // -----------------------------------------------------------
+    
+    /**
+     * Delete the supplied triple from default graph of the database.
+     */
     void delete(Triple t);
+    
+    /**
+     * Delete the supplied triple from the specified graph of the database.
+     * 
+     * @param graphName the graph to delete the triples from; may be null to 
indicate the default graph
+     */
     void delete(Node graphName, Triple t);
+    
+    /**
+     * Delete each of the triples in the supplied Iterable from the specified 
graph of the database.
+     * 
+     * @param graphName the graph to delete the triples from; may be null to 
indicate the default graph
+     */
     void delete(Node graphName, Iterable<? extends Triple> triples);
+    
+    /**
+     * Delete each of the triples in the supplied Iterator from the specified 
graph of the database.
+     * 
+     * @param graphName the graph to delete the triples from; may be null to 
indicate the default graph
+     */
     void delete(Node graphName, Iterator<? extends Triple> tripleIter);
+    
+    /**
+     * Delete all of the triples in the supplied Graph object from the 
specified graph of the database.
+     * 
+     * @param graphName the graph to delete the triples from; may be null to 
indicate the default graph
+     */
     void delete(Node graphName, Graph g);
+
+    /**
+     * Read an InputStream and parse into triples that are then deleted from 
the specified graph of the database.
+     * <p>
+     * <strong>Note:</strong> If the Lang is a Quad language (such as NQUADS 
or TRIG) then any graph names in the
+     * InputStream will be ignored in favor of the graph name provided as an 
argument to this method.
+     * 
+     * @param graphName the graph to delete the triples from; may be null to 
indicate the default graph
+     * @param in an InputStream containing serialized quads
+     * @param lang the language of the supplied InputStream; must be a Quad 
language (such as NQUADS or TRIG)
+     */
     void delete(Node graphName, InputStream in, Lang lang);
+
+    /**
+     * Read an InputStream and parse into triples that are then deleted from 
the specified graph of the database.
+     * <p>
+     * <strong>Note:</strong> If the Lang is a Quad language (such as NQUADS 
or TRIG) then any graph names in the
+     * InputStream will be ignored in favor of the graph name provided as an 
argument to this method.
+     * 
+     * @param graphName the graph to delete the triples from; may be null to 
indicate the default graph
+     * @param in an InputStream containing serialized quads
+     * @param lang the language of the supplied InputStream; must be a Quad 
language (such as NQUADS or TRIG)
+     * @param base Base IRI
+     */
     void delete(Node graphName, InputStream in, Lang lang, String base);
+    
+    
+    
+    // Quads
+    // -----------------------------------------------------------
+    
+    /**
+     * Delete the supplied quad from the database.
+     */
+    void delete(Quad q);
+    
+    /**
+     * Delete each of the quads in the supplied Iterable from the database.
+     */
+    void delete(Iterable<? extends Quad> quads);
+    
+    /**
+     * Delete each of the quads in the supplied Iterator from the database.
+     */
+    void delete(Iterator<? extends Quad> quadIter);
+    
+    /**
+     * Delete all of the quads in the supplied DatasetGraph from the database.
+     */
+    void delete(DatasetGraph dsg);
+    
+    /**
+     * Read an InputStream and parse into quads that are then deleted from the 
database.
+     * <p>
+     * <strong>Note:</strong> The Lang must be a Quad language (such as NQUADS 
or TRIG).  If you have a
+     * triples language, then use {@link #delete(Node, InputStream, Lang)} 
instead.
+     * 
+     * @param in an InputStream containing serialized quads
+     * @param lang the language of the supplied InputStream; must be a Quad 
language (such as NQUADS or TRIG)
+     */
+    void delete(InputStream in, Lang lang);
+    
+    /**
+     * Read an InputStream and parse into quads that are then deleted from the 
database.
+     * <p>
+     * <strong>Note:</strong> The Lang must be a Quad language (such as NQUADS 
or TRIG).  If you have a
+     * triples language, then use {@link #delete(Node, InputStream, Lang)} 
instead.
+     * 
+     * @param in an InputStream containing serialized quads
+     * @param lang the language of the supplied InputStream; must be a Quad 
language (such as NQUADS or TRIG)
+     * @param base Base IRI
+     */
+    void delete(InputStream in, Lang lang, String base);
 }
 

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateExecution.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateExecution.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateExecution.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateExecution.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,29 @@
+/*
+ * 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.client;
+
+import org.apache.jena.atlas.iterator.Action ;
+
+/**
+ * 
+ */
+public interface UpdateExecution
+{
+    void execUpdate(Action<Updater> action);
+}

Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateInserter.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateInserter.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateInserter.java
 (original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateInserter.java
 Thu Apr  9 02:22:47 2015
@@ -18,40 +18,129 @@
 
 package org.apache.jena.client;
 
-import java.io.InputStream;
-import java.util.Iterator;
+import java.io.InputStream ;
+import java.util.Iterator ;
 
-import org.apache.jena.atlas.lib.Closeable;
-import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.Lang ;
 
-import com.hp.hpl.jena.graph.Graph;
-import com.hp.hpl.jena.graph.Node;
-import com.hp.hpl.jena.graph.Triple;
-import com.hp.hpl.jena.sparql.core.DatasetGraph;
-import com.hp.hpl.jena.sparql.core.Quad;
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.Quad ;
 
 /**
- * Represents a streamable SPARQL INSERT DATA operation. 
+ * Represents a streamable SPARQL Update INSERT DATA operation. 
  */
-public interface UpdateInserter extends Closeable
+public interface UpdateInserter
 {
-    // Quads
-    void insert(Quad q);
-    void insert(Iterable<? extends Quad> quads);
-    void insert(Iterator<? extends Quad> quadIter);
-    void insert(DatasetGraph dsg);
-    void insert(InputStream in, Lang lang);  // Lang must be NQUADS or TRIG
-    void insert(InputStream in, Lang lang, String base);  // Lang must be 
NQUADS or TRIG
-    
     // Triples
+    // -----------------------------------------------------------
+    
+    /**
+     * Insert the supplied triple into default graph of the database.
+     */
     void insert(Triple t);
+    
+    /**
+     * Insert the supplied triple into the specified graph of the database.
+     * 
+     * @param graphName the graph to insert the triples into; may be null to 
indicate the default graph
+     */
     void insert(Node graphName, Triple t);
+    
+    /**
+     * Insert each of the triples in the supplied Iterable into the specified 
graph of the database.
+     * 
+     * @param graphName the graph to insert the triples into; may be null to 
indicate the default graph
+     */
     void insert(Node graphName, Iterable<? extends Triple> triples);
+    
+    /**
+     * Insert each of the triples in the supplied Iterator into the specified 
graph of the database.
+     * 
+     * @param graphName the graph to insert the triples into; may be null to 
indicate the default graph
+     */
     void insert(Node graphName, Iterator<? extends Triple> tripleIter);
+    
+    /**
+     * Insert all of the triples in the supplied Graph object into the 
specified graph of the database.
+     * 
+     * @param graphName the graph to insert the triples into; may be null to 
indicate the default graph
+     */
     void insert(Node graphName, Graph g);
+
+    /**
+     * Read an InputStream and parse into triples that are then inserted into 
the specified graph of the database.
+     * <p>
+     * <strong>Note:</strong> If the Lang is a Quad language (such as NQUADS 
or TRIG) then any graph names in the
+     * InputStream will be ignored in favor of the graph name provided as an 
argument to this method.
+     * 
+     * @param graphName the graph to insert the triples into; may be null to 
indicate the default graph
+     * @param in an InputStream containing serialized quads
+     * @param lang the language of the supplied InputStream; must be a Quad 
language (such as NQUADS or TRIG)
+     */
     void insert(Node graphName, InputStream in, Lang lang);
+
+    /**
+     * Read an InputStream and parse into triples that are then inserted into 
the specified graph of the database.
+     * <p>
+     * <strong>Note:</strong> If the Lang is a Quad language (such as NQUADS 
or TRIG) then any graph names in the
+     * InputStream will be ignored in favor of the graph name provided as an 
argument to this method.
+     * 
+     * @param graphName the graph to insert the triples into; may be null to 
indicate the default graph
+     * @param in an InputStream containing serialized quads
+     * @param lang the language of the supplied InputStream; must be a Quad 
language (such as NQUADS or TRIG)
+     * @param base Base IRI
+     */
     void insert(Node graphName, InputStream in, Lang lang, String base);
-    //void insert(Node graphName, IRI sourceDocument);
     
+    
+    
+    // Quads
+    // -----------------------------------------------------------
+    
+    /**
+     * Insert the supplied quad into the database.
+     */
+    void insert(Quad q);
+    
+    /**
+     * Insert each of the quads in the supplied Iterable into the database.
+     */
+    void insert(Iterable<? extends Quad> quads);
+    
+    /**
+     * Insert each of the quads in the supplied Iterator into the database.
+     */
+    void insert(Iterator<? extends Quad> quadIter);
+    
+    /**
+     * Insert all of the quads in the supplied DatasetGraph into the database.
+     */
+    void insert(DatasetGraph dsg);
+    
+    /**
+     * Read an InputStream and parse into quads that are then inserted into 
the database.
+     * <p>
+     * <strong>Note:</strong> The Lang must be a Quad language (such as NQUADS 
or TRIG).  If you have a
+     * triples language, then use {@link #insert(Node, InputStream, Lang)} 
instead.
+     * 
+     * @param in an InputStream containing serialized quads
+     * @param lang the language of the supplied InputStream; must be a Quad 
language (such as NQUADS or TRIG)
+     */
+    void insert(InputStream in, Lang lang);
+    
+    /**
+     * Read an InputStream and parse into quads that are then inserted into 
the database.
+     * <p>
+     * <strong>Note:</strong> The Lang must be a Quad language (such as NQUADS 
or TRIG).  If you have a
+     * triples language, then use {@link #insert(Node, InputStream, Lang)} 
instead.
+     * 
+     * @param in an InputStream containing serialized quads
+     * @param lang the language of the supplied InputStream; must be a Quad 
language (such as NQUADS or TRIG)
+     * @param base Base IRI
+     */
+    void insert(InputStream in, Lang lang, String base);
 }
 

Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateQuerier.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateQuerier.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateQuerier.java
 (original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateQuerier.java
 Thu Apr  9 02:22:47 2015
@@ -17,16 +17,15 @@
  */
 package org.apache.jena.client;
 
-import java.util.Iterator;
+import java.util.Iterator ;
 
-import org.apache.jena.atlas.lib.Closeable;
+import com.hp.hpl.jena.query.ParameterizedSparqlString ;
+import com.hp.hpl.jena.update.Update ;
 
-import com.hp.hpl.jena.query.ParameterizedSparqlString;
-import com.hp.hpl.jena.update.Update;
-
-// TODO I don't like this name... The idea of this class is it can do all 
SPARQL 1.1 Update operations,
-// but they all must be contained in an object, so it isn't suitable for 
streaming large quads.
-public interface UpdateQuerier extends Closeable
+/**
+ * Represents non-INSERT/DELETE DATA update query operations
+ */
+public interface UpdateQuerier
 {
     /**
      * Execute an update query by parsing from a string.
@@ -49,11 +48,24 @@ public interface UpdateQuerier extends C
      */
     void update(String updateQuery, String baseURI);
     
-//    void update(String updateQuery, Syntax syntax);
-    
+    /**
+     * Execute an update query represented by the specified Update object.
+     * 
+     * @param update The update request as an Update object
+     */
     void update(Update update);
     
-    void update(Iterator<? extends Update> updateIter);
-    
+    /**
+     * Execute each update query represented in the specified Iterable of 
Update objects.
+     * 
+     * @param updateIter An Iterable of Update objects
+     */
     void update(Iterable<? extends Update> updates);
+
+    /**
+     * Execute each update query represented in the specified Iterator of 
Update objects.
+     * 
+     * @param updateIter An Iterator of Update objects
+     */
+    void update(Iterator<? extends Update> updateIter);
 }

Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateStatementWrapper.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateStatementWrapper.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateStatementWrapper.java
 (original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdateStatementWrapper.java
 Thu Apr  9 02:22:47 2015
@@ -17,7 +17,7 @@
  */
 package org.apache.jena.client;
 
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeUnit ;
 
 class UpdateStatementWrapper implements UpdateStatement
 {
@@ -41,12 +41,6 @@ class UpdateStatementWrapper implements
     }
 
     @Override
-    public void close()
-    {
-        wrappedObject.close();
-    }
-
-    @Override
     public void cancel()
     {
         wrappedObject.cancel();

Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/Updater.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/Updater.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/Updater.java 
(original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/Updater.java 
Thu Apr  9 02:22:47 2015
@@ -18,10 +18,16 @@
 
 package org.apache.jena.client;
 
-import org.apache.jena.atlas.lib.Closeable;
-
-
-public interface Updater extends UpdateInserter, UpdateDeleter, UpdateQuerier, 
Closeable
+/**
+ * An {@link Updater} provides an interface for creating a single SPARQL 
Update request that may consist
+ * of many separate Update operations.  All operations submitted to an {@code 
Updater} will be executed atomically.
+ * The term 'atomically' means that a single request will result in either no 
effect or a complete effect, regardless
+ * of the number of operations that may be present in the request.
+ * <p>
+ * The {@code Updater} is designed to be fully streaming (if the underlying 
database supports it).  This allows
+ * for an arbitrary number of inserts, deletes, and queries to be performed in 
a single atomic request.
+ */
+public interface Updater extends UpdateInserter, UpdateDeleter, UpdateQuerier
 {
     
 }

Modified: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdaterWrapper.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdaterWrapper.java?rev=1672230&r1=1672229&r2=1672230&view=diff
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdaterWrapper.java
 (original)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/UpdaterWrapper.java
 Thu Apr  9 02:22:47 2015
@@ -17,18 +17,18 @@
  */
 package org.apache.jena.client;
 
-import java.io.InputStream;
-import java.util.Iterator;
+import java.io.InputStream ;
+import java.util.Iterator ;
 
-import org.apache.jena.riot.Lang;
+import org.apache.jena.riot.Lang ;
 
-import com.hp.hpl.jena.graph.Graph;
-import com.hp.hpl.jena.graph.Node;
-import com.hp.hpl.jena.graph.Triple;
-import com.hp.hpl.jena.query.ParameterizedSparqlString;
-import com.hp.hpl.jena.sparql.core.DatasetGraph;
-import com.hp.hpl.jena.sparql.core.Quad;
-import com.hp.hpl.jena.update.Update;
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.query.ParameterizedSparqlString ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+import com.hp.hpl.jena.update.Update ;
 
 class UpdaterWrapper implements Updater
 {
@@ -40,12 +40,6 @@ class UpdaterWrapper implements Updater
     }
 
     @Override
-    public void close()
-    {
-        wrappedObject.close();
-    }
-    
-    @Override
     public void insert(Triple t)
     {
         wrappedObject.insert(t);

Added: 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/AutoCommitQueryExecution.java
URL: 
http://svn.apache.org/viewvc/jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/AutoCommitQueryExecution.java?rev=1672230&view=auto
==============================================================================
--- 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/AutoCommitQueryExecution.java
 (added)
+++ 
jena/Experimental/jena-client/src/main/java/org/apache/jena/client/graph/AutoCommitQueryExecution.java
 Thu Apr  9 02:22:47 2015
@@ -0,0 +1,236 @@
+/*
+ * 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.client.graph;
+
+import java.util.Iterator ;
+import java.util.concurrent.TimeUnit ;
+
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.query.Dataset ;
+import com.hp.hpl.jena.query.Query ;
+import com.hp.hpl.jena.query.QueryExecution ;
+import com.hp.hpl.jena.query.QuerySolution ;
+import com.hp.hpl.jena.query.ReadWrite ;
+import com.hp.hpl.jena.query.ResultSet ;
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.sparql.core.Transactional ;
+import com.hp.hpl.jena.sparql.util.Context ;
+
+/**
+ * Wraps a QueryExecution and provides auto commit transaction support.
+ */
+class AutoCommitQueryExecution implements QueryExecution
+{
+    private final QueryExecution qe;
+    private final Transactional tx;
+    private boolean openTx;
+    
+    public AutoCommitQueryExecution(QueryExecution qe, Transactional tx)
+    {
+        if (null == qe) throw new NullPointerException("qe must not be null");
+        if (null == tx) throw new NullPointerException("tx must not be null");
+        this.qe = qe;
+        this.tx = tx;
+        this.openTx = false;
+    }
+    
+    // Execution begins, but does not finish until close() is called
+    
+    @Override
+    public ResultSet execSelect()
+    {
+        tx.begin(ReadWrite.READ);
+        openTx = true;
+        return qe.execSelect();
+    }
+    
+    @Override
+    public Iterator<Triple> execConstructTriples()
+    {
+        tx.begin(ReadWrite.READ);
+        openTx = true;
+        return qe.execConstructTriples() ;
+    }
+    
+    @Override
+    public Iterator<Triple> execDescribeTriples()
+    {
+        tx.begin(ReadWrite.READ);
+        openTx = true;
+        return qe.execDescribeTriples() ;
+    }
+    
+    @Override
+    public void close()
+    {
+        qe.close();
+        if (openTx)
+        {
+            tx.end();
+            openTx = false;
+        }
+    }
+    
+    // Execution occurs completely, so entire transaction can be performed
+    
+    @Override
+    public Model execConstruct()
+    {
+        tx.begin(ReadWrite.READ);
+        try
+        {
+            return qe.execConstruct();
+        }
+        finally
+        {
+            tx.end();
+        }
+    }
+
+    @Override
+    public Model execConstruct(Model model)
+    {
+        tx.begin(ReadWrite.READ);
+        try
+        {
+            return qe.execConstruct(model);
+        }
+        finally
+        {
+            tx.end();
+        }
+    }
+
+    @Override
+    public Model execDescribe()
+    {
+        tx.begin(ReadWrite.READ);
+        try
+        {
+            return qe.execDescribe();
+        }
+        finally
+        {
+            tx.end();
+        }
+    }
+
+    @Override
+    public Model execDescribe(Model model)
+    {
+        tx.begin(ReadWrite.READ);
+        try
+        {
+            return qe.execDescribe(model);
+        }
+        finally
+        {
+            tx.end();
+        }
+    }
+
+    @Override
+    public boolean execAsk()
+    {
+        tx.begin(ReadWrite.READ);
+        try
+        {
+            return qe.execAsk();
+        }
+        finally
+        {
+            tx.end();
+        }
+    }
+    
+    
+    // Methods below simply delegate to the wrapped QueryExecution
+    
+    @Override
+    public void setInitialBinding(QuerySolution binding)
+    {
+        qe.setInitialBinding(binding) ;
+    }
+
+    @Override
+    public Dataset getDataset()
+    {
+        return qe.getDataset() ;
+    }
+
+    @Override
+    public Context getContext()
+    {
+        return qe.getContext() ;
+    }
+    
+    @Override
+    public Query getQuery()
+    {
+        return qe.getQuery() ;
+    }
+
+    @Override
+    public void abort()
+    {
+        qe.abort() ;
+    }
+
+    @Override
+    public boolean isClosed()
+    {
+        return qe.isClosed() ;
+    }
+
+    @Override
+    public void setTimeout(long timeout, TimeUnit timeoutUnits)
+    {
+        qe.setTimeout(timeout, timeoutUnits) ;
+    }
+
+    @Override
+    public void setTimeout(long timeout)
+    {
+        qe.setTimeout(timeout) ;
+    }
+
+    @Override
+    public void setTimeout(long timeout1, TimeUnit timeUnit1, long timeout2, 
TimeUnit timeUnit2)
+    {
+        qe.setTimeout(timeout1, timeUnit1, timeout2, timeUnit2) ;
+    }
+
+    @Override
+    public void setTimeout(long timeout1, long timeout2)
+    {
+        qe.setTimeout(timeout1, timeout2) ;
+    }
+
+    @Override
+    public long getTimeout1()
+    {
+        return qe.getTimeout1() ;
+    }
+
+    @Override
+    public long getTimeout2()
+    {
+        return qe.getTimeout2() ;
+    }
+}


Reply via email to