You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2014/01/05 19:05:51 UTC
svn commit: r1555594 [1/2] - in /jena/Experimental/rdfpatch: ./ src/
src/main/ src/main/java/ src/main/java/dev/ src/main/java/org/
src/main/java/org/apache/ src/main/java/org/apache/jena/
src/main/java/org/apache/jena/rdfpatch/ src/main/java/org/apach...
Author: andy
Date: Sun Jan 5 18:05:50 2014
New Revision: 1555594
URL: http://svn.apache.org/r1555594
Log:
RDF Patch processor.
Fully transactional (serializable) in-memory datasets.
Added:
jena/Experimental/rdfpatch/pom.xml
jena/Experimental/rdfpatch/src/
jena/Experimental/rdfpatch/src/main/
jena/Experimental/rdfpatch/src/main/java/
jena/Experimental/rdfpatch/src/main/java/dev/
jena/Experimental/rdfpatch/src/main/java/dev/MainRec.java
jena/Experimental/rdfpatch/src/main/java/dev/PROJECT_Patch.java
jena/Experimental/rdfpatch/src/main/java/org/
jena/Experimental/rdfpatch/src/main/java/org/apache/
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetChangesTuples.java
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetGraphPatchTransaction.java
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetGraphPlayer.java
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/PatchAssembler.java
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/RDFPatch.java
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/Vocab.java
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/CommsException.java
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStream.java
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStreamBase.java
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStreamWrapper.java
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStream.java
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStreamWrapper.java
jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStreamWriter.java
jena/Experimental/rdfpatch/src/test/
jena/Experimental/rdfpatch/src/test/java/
jena/Experimental/rdfpatch/src/test/java/org/
jena/Experimental/rdfpatch/src/test/java/org/apache/
jena/Experimental/rdfpatch/src/test/java/org/apache/jena/
jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/
jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TS_RDFPatch.java
jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TestPatchPlayer.java
jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TestRDFPatch.java
jena/Experimental/rdfpatch/src/test/java/org/apache/jena/riot/
jena/Experimental/rdfpatch/src/test/java/org/apache/jena/riot/tio/
jena/Experimental/rdfpatch/src/test/java/org/apache/jena/riot/tio/TestTokenIO.java
Added: jena/Experimental/rdfpatch/pom.xml
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/pom.xml?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/pom.xml (added)
+++ jena/Experimental/rdfpatch/pom.xml Sun Jan 5 18:05:50 2014
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-rdfpatch</artifactId>
+ <packaging>jar</packaging>
+ <name>Apache Jena - RDF Patch</name>
+ <version>0.0.1-SNAPSHOT</version>
+
+ <parent>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-parent</artifactId>
+ <version>8-SNAPSHOT</version>
+ <relativePath>../jena-parent</relativePath>
+ </parent>
+
+ <!-- Need if the parent is a snapshot -->
+ <repositories>
+ <repository>
+ <id>apache.snapshots</id>
+ <name>Apache Snapshot Repository</name>
+ <url>http://repository.apache.org/snapshots</url>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ </repository>
+ </repositories>
+
+ <description>RDF Patch http://afs.github.io/rdf-patch/</description>
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/jena/tags/jena-2.11.1-SNAPSHOT/jena-rdfpatch</connection>
+ <developerConnection>scm:svn:http://svn.apache.org/repos/asf/jena/tags/jena-2.11.1-SNAPSHOT/jena-rdfpatch</developerConnection>
+ <url>https://svn.apache.org/repos/asf/jena/tags/jena-2.11.1-SNAPSHOT/jena-rdfpatch</url>
+ </scm>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-arq</artifactId>
+ <version>2.11.1-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-arq</artifactId>
+ <classifier>tests</classifier>
+ <version>2.11.1-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-core</artifactId>
+ <version>2.11.1-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.jena</groupId>
+ <artifactId>jena-core</artifactId>
+ <classifier>tests</classifier>
+ <version>2.11.1-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <!--
+ <resources>
+ <resource>
+ <filtering>false</filtering>
+ <directory>src/main/resources</directory>
+ <excludes>
+ <exclude>org/apache/jena/patch/patch-properties.xml</exclude>
+ </excludes>
+ </resource>
+ <resource>
+ <filtering>true</filtering>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>org/apache/jena/patch/patch-properties.xml</include>
+ </includes>
+ </resource>
+ </resources>
+ -->
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>**/TS_*.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <!-- <phase>package</phase> package is the default -->
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>attach-sources-test</id>
+ <goals>
+ <goal>test-jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <version>true</version>
+ <show>public</show>
+ <quiet>true</quiet>
+ <encoding>UTF-8</encoding>
+ <windowtitle>Apache Jena - RDF Patch</windowtitle>
+ <doctitle>Apache Jena - RDF Patch ${project.version}</doctitle>
+ <bottom>Licenced under the Apache License, Version 2.0</bottom>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ </plugin>
+
+ </plugins>
+ </build>
+
+ <reporting>
+ <!-- <outputDirectory>${project.build.directory}/site</outputDirectory> -->
+ </reporting>
+
+</project>
Added: jena/Experimental/rdfpatch/src/main/java/dev/MainRec.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/dev/MainRec.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/dev/MainRec.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/dev/MainRec.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,124 @@
+/**
+ * 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 dev;
+
+import java.io.StringWriter ;
+
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.logging.LogCtl ;
+import org.apache.jena.rdfpatch.DatasetChangesTuples ;
+import org.apache.jena.rdfpatch.DatasetGraphPatchTransaction ;
+import org.apache.jena.rdfpatch.DatasetGraphPlayer ;
+import org.apache.jena.rdfpatch.RDFPatch ;
+import org.apache.jena.riot.tio.TokenInputStream ;
+import org.apache.jena.riot.tio.TokenInputStreamBase ;
+import org.apache.jena.riot.tio.TokenOutputStreamWriter ;
+import org.apache.jena.riot.tokens.Tokenizer ;
+import org.apache.jena.riot.tokens.TokenizerFactory ;
+
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.NodeFactory ;
+import com.hp.hpl.jena.query.ReadWrite ;
+import com.hp.hpl.jena.sparql.core.* ;
+import com.hp.hpl.jena.sparql.sse.SSE ;
+
+public class MainRec
+{
+ static { LogCtl.setCmdLogging() ; }
+
+ public static void main(String[] args) {
+ DatasetGraph dsg1 = DatasetGraphFactory.createMem() ;
+ DatasetGraphPatchTransaction dsg = new DatasetGraphPatchTransaction(dsg1) ;
+ Quad q = SSE.parseQuad("(:g <s> <p> _:a)") ;
+ dsg.begin(ReadWrite.WRITE);
+ dsg.add(q) ;
+ SSE.write(dsg) ;
+ dsg.abort() ;
+ dsg.end();
+ SSE.write(dsg) ;
+
+ dsg.begin(ReadWrite.WRITE);
+ dsg.add(q) ;
+ dsg.commit() ;
+ dsg.end();
+ SSE.write(dsg) ;
+
+ dsg.begin(ReadWrite.READ);
+ Iter.toList(dsg.find()) ;
+ dsg.end();
+ System.out.println("DONE") ;
+ }
+
+ public static void main1(String[] args)
+ {
+ DatasetGraph dsg = DatasetGraphFactory.createMem() ;
+ if ( false )
+ dsg = new DatasetGraphSimpleMem() ;
+
+ StringWriter sw = new StringWriter() ;
+ TokenOutputStreamWriter out = new TokenOutputStreamWriter(null, sw) ;
+ DatasetChanges changeLogger = new DatasetChangesTuples(out) ;
+
+ dsg = RDFPatch.record(dsg, changeLogger) ;
+ out.setPrefixMapping("", "http://example/") ;
+
+ //changeLogger.begin(ReadWrite.WRITE) ;
+ changeLogger.start() ;
+ Quad q = SSE.parseQuad("(:g <s> <p> _:a)") ;
+ Node b = q.getObject() ;
+ dsg.add(q) ;
+ dsg.delete(q) ;
+ dsg.delete(q) ;
+
+// changeLogger.commit() ;
+// changeLogger.end() ;
+
+ Graph g = SSE.parseGraph("(graph (<s1> <p1> 3) (<s2> <p2> 2))") ;
+ dsg.addGraph(NodeFactory.createURI("graph"), g) ;
+ changeLogger.finish();
+ out.flush();
+
+ SSE.write(dsg) ;
+
+ System.out.println("------------------------------") ;
+ System.out.print(sw.toString()) ;
+
+ Tokenizer t = TokenizerFactory.makeTokenizerString(sw.toString()) ;
+ TokenInputStream in = new TokenInputStreamBase(null, t) ;
+// while(in.hasNext())
+// {
+// List<Token> line = in.next() ;
+// System.out.println(line) ;
+// }
+
+ System.out.println("------------------------------") ;
+
+ DatasetGraph dsg2 = DatasetGraphFactory.createMem() ;
+ DatasetGraphPlayer.play(in, dsg2) ;
+ SSE.write(dsg2) ;
+
+ Node x = dsg2.getGraph(NodeFactory.createURI("http://example/g")).find(null, null, null).next().getObject() ;
+ System.out.println(x.getBlankNodeLabel()) ;
+ System.out.println(x.equals(b)) ;
+ System.out.println("DONE") ;
+ }
+
+}
+
Added: jena/Experimental/rdfpatch/src/main/java/dev/PROJECT_Patch.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/dev/PROJECT_Patch.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/dev/PROJECT_Patch.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/dev/PROJECT_Patch.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,33 @@
+/**
+ * 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 dev;
+
+
+public class PROJECT_Patch {
+ // How to end changes and flush.
+
+ // Is it time to have a universal event handled for add/delete?
+ // DatasetGraph -> DatasetGraph+txn
+
+ // Consider query engine registries.
+ // How to have wrappers yet still pass down to concrete DSGs.
+ // Just a case of a Plan that passwses to the wrapped DSG?
+
+ // Jena3: dsg.exec(op) ?
+}
Added: jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetChangesTuples.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetChangesTuples.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetChangesTuples.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetChangesTuples.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,118 @@
+/**
+ * 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.rdfpatch;
+
+import java.io.PrintStream ;
+
+import org.apache.jena.atlas.lib.Sync ;
+import org.apache.jena.riot.tio.TokenInputStream ;
+import org.apache.jena.riot.tio.TokenOutputStream ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.query.ReadWrite ;
+import com.hp.hpl.jena.sparql.core.DatasetChanges ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.QuadAction ;
+import com.hp.hpl.jena.sparql.core.Transactional ;
+import com.hp.hpl.jena.sparql.util.FmtUtils ;
+
+/** Write changes to a TokenOutputStream, often going to a file.
+ * The reverse operation of applying a record stream is provided by
+ * {@linkplain DatasetGraphPlayer#play(TokenInputStream, DatasetGraph)}.
+ */
+
+public class DatasetChangesTuples implements DatasetChanges, Transactional, Sync
+{
+ private TokenOutputStream out ;
+
+ public DatasetChangesTuples(TokenOutputStream out) { this.out = out; }
+
+ @Override
+ public void start()
+ {}
+
+ @Override
+ public void finish()
+ { out.flush() ; }
+
+ @Override
+ public void change(QuadAction action, Node g, Node s, Node p, Node o)
+ {
+ record(action, g, s, p, o) ;
+ }
+
+ static final String SEP1 = ", " ; // TAB is good.
+ static final String SEP2 = "\n" ;
+
+ private void record(QuadAction action, Node g, Node s, Node p, Node o)
+ {
+ out.startTuple() ;
+ out.sendWord(action.label) ;
+ out.sendNode(g) ;
+ out.sendNode(s) ;
+ out.sendNode(p) ;
+ out.sendNode(o) ;
+ out.endTuple() ;
+ }
+
+ private void print(PrintStream out, Node x)
+ {
+ String str = FmtUtils.stringForNode(x) ;
+ out.print(str) ;
+ }
+
+ private void outOneWord(String word) {
+ out.startTuple() ;
+ out.sendWord(word) ;
+ out.endTuple() ;
+ }
+
+ // Need to record at success/failure of transaction.
+
+ boolean isInTransaction = false ;
+
+ @Override
+ public void begin(ReadWrite readWrite)
+ { outOneWord("BEGIN/"+readWrite.name()) ; isInTransaction = true ; }
+
+ @Override
+ public void commit()
+ { outOneWord("COMMIT") ; isInTransaction = false ;}
+
+ @Override
+ public void abort()
+ { outOneWord("ABORT") ; isInTransaction = false ;}
+
+ @Override
+ public boolean isInTransaction()
+ {
+ return isInTransaction ;
+ }
+
+ @Override
+ public void end()
+ { outOneWord("END") ; }
+
+ @Override
+ public void sync() {
+ out.flush() ;
+ }
+
+}
+
Added: jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetGraphPatchTransaction.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetGraphPatchTransaction.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetGraphPatchTransaction.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetGraphPatchTransaction.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,110 @@
+/**
+ * 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.rdfpatch;
+
+import org.apache.jena.rdfpatch.DatasetGraphPlayer.Direction ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.query.ReadWrite ;
+import com.hp.hpl.jena.sparql.core.* ;
+
+/** Provide transactional semantics to a DatasetGraph.
+ * Changes are made the dataset immediately and an undo log is kept.
+ * If {@code abort()} is called, the changes are undone.
+ * Implicitly uses MRSW locking; there is no true parallel readers
+ * when a write transaction is active.
+ */
+
+public class DatasetGraphPatchTransaction extends DatasetGraphWithLock {
+ private final DatasetChangesTransaction delta ;
+ // The original dataset. Used as the replay target.
+ private final DatasetGraph dataset ;
+ // The dataset with a change monitor.
+ private final DatasetGraph datasetMonitor ;
+
+ public DatasetGraphPatchTransaction(DatasetGraph dsg) {
+ // Instead of passing in the dataset, we override get()
+ super(null) ;
+ delta = new DatasetChangesTransaction() ;
+ this.dataset = dsg ;
+ DatasetGraphMonitor dsgm = new DatasetGraphMonitor(dsg, delta) ;
+ datasetMonitor = dsgm ;
+ }
+
+ @Override
+ protected DatasetGraph get() { return datasetMonitor ; }
+
+ @Override
+ protected void _begin(ReadWrite readWrite) {
+ switch (readWrite) {
+ case READ : break ;
+ case WRITE :
+ delta.start() ;
+ break ;
+ default :
+ }
+ super._begin(readWrite) ;
+ }
+
+ @Override
+ protected void _commit() {
+ delta.finish() ;
+ super._commit() ;
+ }
+
+ @Override
+ protected void _abort() {
+ if ( isTransactionType(ReadWrite.WRITE) )
+ DatasetGraphPlayer.play(delta.get().getActions(), dataset, Direction.BACKWARDS) ;
+ // fakery for super.abort()
+ if ( isTransactionType(ReadWrite.WRITE) )
+ super._end() ;
+ }
+
+ @Override
+ protected void _end() {
+ delta.finish() ;
+ super._end() ;
+ }
+
+ static class DatasetChangesTransaction implements DatasetChanges {
+ private DatasetChangesCapture changes ;
+ public DatasetChangesCapture get() { return changes ; }
+
+ public DatasetChangesTransaction() {
+ }
+
+ @Override
+ public void start() {
+ changes = new DatasetChangesCapture() ;
+ changes.start() ;
+ }
+
+ @Override
+ public void change(QuadAction qaction, Node g, Node s, Node p, Node o) {
+ changes.change(qaction, g, s, p, o) ;
+ }
+
+ @Override
+ public void finish() {
+ if ( changes != null )
+ changes.finish() ;
+ }
+ }
+}
Added: jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetGraphPlayer.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetGraphPlayer.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetGraphPlayer.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/DatasetGraphPlayer.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,195 @@
+/**
+ * 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.rdfpatch;
+
+import java.util.Iterator ;
+import java.util.List ;
+import java.util.ListIterator ;
+
+import org.apache.jena.atlas.lib.Pair ;
+import org.apache.jena.riot.system.RiotLib ;
+import org.apache.jena.riot.tio.TokenInputStream ;
+import org.apache.jena.riot.tokens.Token ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.sparql.core.DatasetChangesCapture ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+import com.hp.hpl.jena.sparql.core.QuadAction ;
+
+public class DatasetGraphPlayer
+{
+ enum Direction { FORWARDS, BACKWARDS }
+
+ /**
+ * @see DatasetChangesCapture
+ */
+ public static void play(List<Pair<QuadAction, Quad>> actions, DatasetGraph dsg, Direction direction)
+ {
+ Iterator<Pair<QuadAction, Quad>> iter =
+ (Direction.BACKWARDS == direction)
+ ? new ListIteratorReverse<Pair<QuadAction, Quad>>(actions.listIterator(actions.size()))
+ : actions.listIterator() ;
+
+ loop:
+ while ( iter.hasNext() ) {
+ Pair<QuadAction, Quad> p = iter.next() ;
+ QuadAction action = p.getLeft() ;
+ Quad quad = p.getRight() ;
+
+ boolean addOp = true ;
+ switch (action) {
+ case ADD :
+ break ;
+ case DELETE :
+ addOp = false ;
+ break ;
+ case NO_ADD :
+ case NO_DELETE :
+ default :
+ continue loop ;
+ }
+
+ if ( direction == Direction.BACKWARDS )
+ addOp = ! addOp ;
+
+ if ( addOp )
+ dsg.add(quad) ;
+ else
+ dsg.delete(quad) ;
+ }
+ }
+
+ /** Reverse the mainings of next/previous on a ListIterator */
+ static class ListIteratorReverse<T> implements ListIterator<T> {
+ private final ListIterator<T> iter ;
+
+ ListIteratorReverse(ListIterator<T> iter) {
+ this.iter= iter ;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iter.hasPrevious() ;
+ }
+
+ @Override
+ public T next() {
+ return iter.previous() ;
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return iter.hasNext() ;
+ }
+
+ @Override
+ public T previous() {
+ return iter.next() ;
+ }
+
+ @Override
+ public int nextIndex() {
+ return iter.previousIndex() ;
+ }
+
+ @Override
+ public int previousIndex() {
+ return iter.nextIndex() ;
+ }
+
+ @Override
+ public void remove() { iter.remove() ; }
+
+ @Override
+ public void set(T e) { iter.set(e) ; }
+
+ @Override
+ public void add(T e) { iter.add(e) ; }
+ }
+
+ public static void play(TokenInputStream input, DatasetGraph dsg)
+ {
+ long count = 0 ;
+ long errorCount = 0 ;
+ while(input.hasNext())
+ {
+ List<Token> line = input.next() ;
+ count++ ;
+ if ( line.size() == 0 )
+ continue ;
+ if ( line.size() == 1 )
+ {
+ // Maybe a word
+ continue ;
+ }
+
+ if ( line.size() != 5 ) {
+ errorCount++ ;
+ error("[%d] Bad tuple - length %d", count, line.size() ) ;
+// if ( errorCount > MaxErrors ) {
+// error("Too many errors" ) ;
+// return ;
+// }
+ }
+
+ Token ctl = line.get(0) ;
+ if ( ! ctl.isWord() )
+ error("[%d] No start word",count) ;
+ String str = ctl.getImage() ;
+ if ( str.startsWith("#") )
+ continue ;
+ Node g = asNode(line.get(1)) ;
+ Node s = asNode(line.get(2)) ;
+ Node p = asNode(line.get(3)) ;
+ Node o = asNode(line.get(4)) ;
+
+ boolean addOp = true ;
+
+ if ( str.equals("A") )
+ addOp = true ;
+ else if ( str.equals("D") )
+ addOp = false ;
+ else
+ error("Bad word: "+str) ;
+
+// if ( direction == Direction.BACKWARDS )
+// addOp = ! addOp ;
+
+ if ( addOp )
+ dsg.add(g,s,p,o) ;
+ else
+ dsg.delete(g,s,p,o) ;
+ }
+ }
+
+ private static Node asNode(Token t) {
+ // <_:...> bnodes.
+ if ( t.isIRI() )
+ return RiotLib.createIRIorBNode(t.getImage()) ;
+ return t.asNode() ;
+ }
+
+ private static void error(String fmt, Object...args)
+ {
+ throw new RuntimeException(String.format(fmt,args)) ;
+ }
+
+}
+
Added: jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/PatchAssembler.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/PatchAssembler.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/PatchAssembler.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/PatchAssembler.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,68 @@
+/**
+ * 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.rdfpatch;
+
+import static com.hp.hpl.jena.sparql.util.graph.GraphUtils.exactlyOneProperty ;
+
+import java.io.FileOutputStream ;
+import java.io.IOException ;
+import java.io.OutputStream ;
+
+import org.apache.jena.atlas.io.IO ;
+
+import com.hp.hpl.jena.assembler.Assembler ;
+import com.hp.hpl.jena.assembler.Mode ;
+import com.hp.hpl.jena.assembler.exceptions.AssemblerException ;
+import com.hp.hpl.jena.query.Dataset ;
+import com.hp.hpl.jena.query.DatasetFactory ;
+import com.hp.hpl.jena.rdf.model.Property ;
+import com.hp.hpl.jena.rdf.model.Resource ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.assembler.DatasetAssembler ;
+import com.hp.hpl.jena.sparql.core.assembler.DatasetAssemblerException ;
+
+public class PatchAssembler extends DatasetAssembler
+{
+ private static final String NS = "http://jena.apache.org/rdfpatch#" ;
+
+ static Property pDataset = Vocab.property(NS, "dataset") ;
+ static Property pChangeLog = Vocab.property(NS, "changelog") ;
+
+ @Override
+ public Dataset createDataset(Assembler a, Resource root, Mode mode) {
+ if ( !exactlyOneProperty(root, pDataset) )
+ throw new AssemblerException(root, "No dataset to wrap") ;
+
+ Resource other = getRequiredResource(root, pDataset) ;
+
+ Object obj = super.open(a, other, mode) ;
+ if ( ! ( obj instanceof Dataset ) )
+ throw new DatasetAssemblerException(root, "Not a dataset: "+other) ;
+ DatasetGraph dsg = ((Dataset)obj).asDatasetGraph() ;
+
+ // And where to route the changes.
+
+ String logfile = getUniqueString(root, pChangeLog) ;
+ try {
+ OutputStream outs = new FileOutputStream(logfile) ;
+ DatasetGraph dsgx = RDFPatch.recordChanges(dsg, outs) ;
+ return DatasetFactory.create(dsgx) ;
+ } catch (IOException ex) { IO.exception(ex); return null ; }
+ }
+}
Added: jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/RDFPatch.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/RDFPatch.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/RDFPatch.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/RDFPatch.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,78 @@
+/**
+ * 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.rdfpatch ;
+
+import java.io.InputStream ;
+import java.io.OutputStream ;
+import java.io.Writer ;
+
+import org.apache.jena.atlas.io.IO ;
+import org.apache.jena.riot.tio.TokenInputStream ;
+import org.apache.jena.riot.tio.TokenInputStreamBase ;
+import org.apache.jena.riot.tio.TokenOutputStream ;
+import org.apache.jena.riot.tio.TokenOutputStreamWriter ;
+import org.apache.jena.riot.tokens.Tokenizer ;
+import org.apache.jena.riot.tokens.TokenizerFactory ;
+
+import com.hp.hpl.jena.sparql.core.DatasetChanges ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphMonitor ;
+
+public class RDFPatch {
+ /**
+ * Write changes to an OutputStream. Chnages are written in
+ * <a href="http://afs.github.io/rdf-patch/">RDF Patch</a> format.
+ * When finished, call <code>.sync()<</code> to ensure
+ * buffered changes have been written to the <code>OutputStream</code>.
+ *
+ * @param dsg
+ * @param output Destination
+ * @return DatasetGraph
+ */
+ public static DatasetGraphMonitor recordChanges(DatasetGraph dsg, OutputStream output) {
+ Writer w = IO.asBufferedUTF8(output) ;
+ TokenOutputStream out = new TokenOutputStreamWriter(null, w) ;
+ DatasetChanges changes = new DatasetChangesTuples(out) ;
+ return record(dsg, changes) ;
+ }
+
+ /**
+ * Record changes, sending a record of them to a DatasetChanges processor.
+ *
+ * @param dsg DatasetGraph
+ * @param changes A DatasetChanges processor.
+ * @return DatasetGraph
+ */
+ public static DatasetGraphMonitor record(DatasetGraph dsg, DatasetChanges changes) {
+ DatasetGraphMonitor monitor = new DatasetGraphMonitor(dsg, changes) ;
+ return monitor ;
+ }
+
+ /**
+ * Replay a stream in <a href="http://afs.github.io/rdf-patch/">RDF
+ * Patch</a> format, as might be produced by {@linkplain #recordChanges}
+ * @param dsg
+ * @param input
+ */
+ public static void replayChanges(DatasetGraph dsg, InputStream input) {
+ Tokenizer t = TokenizerFactory.makeTokenizerUTF8(input) ;
+ TokenInputStream in = new TokenInputStreamBase(null, t) ;
+ DatasetGraphPlayer.play(in, dsg) ;
+ }
+}
Added: jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/Vocab.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/Vocab.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/Vocab.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/org/apache/jena/rdfpatch/Vocab.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,41 @@
+/*
+ * 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.rdfpatch;
+
+import com.hp.hpl.jena.rdf.model.Property;
+import com.hp.hpl.jena.rdf.model.Resource;
+import com.hp.hpl.jena.rdf.model.ResourceFactory;
+
+public class Vocab
+{
+ public static Resource type(String namespace, String localName)
+ {
+ return ResourceFactory.createResource(namespace+localName) ;
+ }
+
+ public static Resource resource(String namespace, String localName)
+ {
+ return ResourceFactory.createResource(namespace+localName) ;
+ }
+
+ public static Property property(String namespace, String localName)
+ {
+ return ResourceFactory.createProperty(namespace+localName) ;
+ }
+}
Added: jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/CommsException.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/CommsException.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/CommsException.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/CommsException.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,34 @@
+/*
+ * 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.riot.tio;
+
+public class CommsException extends RuntimeException
+{
+ public CommsException()
+ { super(); }
+
+ public CommsException(String message)
+ { super(message) ; }
+
+ public CommsException(String message, Throwable cause)
+ { super(message, cause) ; }
+
+ public CommsException(Throwable cause)
+ { super(cause) ; }
+}
Added: jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStream.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStream.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStream.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStream.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,31 @@
+/*
+ * 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.riot.tio;
+
+import java.util.Iterator ;
+import java.util.List ;
+
+import org.apache.jena.atlas.lib.Closeable ;
+import org.apache.jena.riot.tokens.Token ;
+
+/** A stream of tokens */
+public interface TokenInputStream extends Iterator<List<Token>>, Iterable<List<Token>>, Closeable
+{
+
+}
Added: jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStreamBase.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStreamBase.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStreamBase.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStreamBase.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,167 @@
+/*
+ * 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.riot.tio ;
+
+import java.util.ArrayList ;
+import java.util.HashMap ;
+import java.util.Iterator ;
+import java.util.List ;
+import java.util.Map ;
+import java.util.NoSuchElementException ;
+
+import org.apache.jena.riot.tokens.PrintTokenizer ;
+import org.apache.jena.riot.tokens.Token ;
+import org.apache.jena.riot.tokens.Tokenizer ;
+import static org.apache.jena.riot.tokens.TokenType.* ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+/** Tokenizer that sorts out prefixes and groups into sequences of token */
+public class TokenInputStreamBase implements TokenInputStream {
+ private static Logger log = LoggerFactory.getLogger(TokenInputStreamBase.class) ;
+ private boolean finished = false ;
+ private final Tokenizer tokens ;
+ private List<Token> list ;
+ private Map<String, String> map = new HashMap<String, String>() ;
+ private String label ;
+
+ public TokenInputStreamBase(String label, Tokenizer tokens) {
+ if ( false )
+ tokens = new PrintTokenizer("InputStream: ", tokens) ;
+ this.tokens = tokens ;
+ this.label = label ;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if ( finished )
+ return false ;
+
+ if ( list != null ) // Already got the reply.
+ return true ;
+
+ try {
+ if ( !tokens.hasNext() ) {
+ finished = true ;
+ return false ;
+ }
+ list = buildOneLine() ;
+ if ( false && log.isDebugEnabled() )
+ log.debug("Tokens: " + list) ;
+ if ( list == null )
+ finished = true ;
+ return list != null ;
+ } catch (Exception ex) {
+ finished = true ;
+ return false ;
+ }
+ }
+
+ private List<Token> buildOneLine() {
+ List<Token> tuple = new ArrayList<Token>() ;
+ boolean isDirective = false ;
+ for (; tokens.hasNext();) {
+ Token token = tokens.next() ;
+
+ if ( token.hasType(DIRECTIVE) )
+ isDirective = true ;
+
+ if ( token.hasType(DOT) ) {
+ if ( tuple.size() > 0 && tuple.get(0).hasType(DIRECTIVE) ) {
+ directive(tuple) ;
+ tuple.clear() ;
+ isDirective = false ;
+ // Start again.
+ continue ;
+ }
+ return tuple ;
+ }
+
+ // Fixup prefix names.
+ if ( !isDirective && token.hasType(PREFIXED_NAME) ) {
+ String ns = map.get(token.getImage()) ;
+ String iri ;
+ if ( ns == null ) {
+ log.warn("Can't resolve '" + token.toString(false) + "'", ns) ;
+ iri = "unresolved:" + token.getImage() + ":" + token.getImage2() ;
+ } else
+ iri = ns + token.getImage2() ;
+ token.setType(IRI) ;
+ token.setImage(iri) ;
+ token.setImage2(null) ;
+ }
+
+ tuple.add(token) ;
+ }
+
+ // No final DOT
+ return tuple ;
+ }
+
+ private void directive(List<Token> tuple) {
+ if ( tuple.size() != 3 )
+ throw new CommsException("Bad directive: " + tuple) ;
+
+ String x = tuple.get(0).getImage() ;
+
+ if ( x.equals("prefix") ) {
+ // Raw - unresolved prefix name.
+ if ( !tuple.get(1).hasType(PREFIXED_NAME) )
+ throw new CommsException("@prefix requires a prefix (found '" + tuple.get(1) + "')") ;
+ if ( tuple.get(1).getImage2().length() != 0 )
+ throw new CommsException("@prefix requires a prefix and no suffix (found '" + tuple.get(1) + "')") ;
+ String prefix = tuple.get(1).getImage() ;
+
+ if ( !tuple.get(2).hasType(IRI) )
+ throw new CommsException("@prefix requires an IRI (found '" + tuple.get(1) + "')") ;
+ String iriStr = tuple.get(2).getImage() ;
+ map.put(prefix, iriStr) ;
+ return ;
+ }
+ throw new CommsException("Unregcognized directive: " + x) ;
+ }
+
+ @Override
+ public List<Token> next() {
+ if ( !hasNext() )
+ throw new NoSuchElementException() ;
+ List<Token> r = list ;
+ if ( log.isDebugEnabled() ) {
+ if ( label != null )
+ log.debug("<< " + label + ": " + r) ;
+ else
+ log.debug("<< " + r.toString()) ;
+ }
+ list = null ;
+ return r ;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException() ;
+ }
+
+ @Override
+ public Iterator<List<Token>> iterator() {
+ return this ;
+ }
+
+ @Override
+ public void close() {}
+}
Added: jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStreamWrapper.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStreamWrapper.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStreamWrapper.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenInputStreamWrapper.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,47 @@
+/*
+ * 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.riot.tio;
+
+import java.util.Iterator ;
+import java.util.List ;
+
+import org.apache.jena.atlas.lib.Closeable ;
+import org.apache.jena.riot.tokens.Token ;
+
+public class TokenInputStreamWrapper implements Iterator<List<Token>>, Iterable<List<Token>>, Closeable
+{
+ private TokenInputStream stream ;
+
+ public TokenInputStreamWrapper(TokenInputStream stream) { this.stream = stream ; }
+
+ @Override
+ public boolean hasNext() { return stream.hasNext() ; }
+
+ @Override
+ public List<Token> next() { return stream.next() ; }
+
+ @Override
+ public void remove() { stream.remove() ; }
+
+ @Override
+ public Iterator<List<Token>> iterator() { return stream.iterator() ; }
+
+ @Override
+ public void close() { stream.close(); }
+}
Added: jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStream.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStream.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStream.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStream.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,40 @@
+/*
+ * 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.riot.tio;
+
+import org.apache.jena.atlas.lib.Closeable ;
+import org.apache.jena.atlas.lib.Sync ;
+import org.apache.jena.riot.tokens.Token ;
+
+import com.hp.hpl.jena.graph.Node ;
+
+public interface TokenOutputStream extends Closeable, Sync
+{
+ public void sendToken(Token token) ;
+ public void sendNode(Node node) ;
+ public void sendString(String string) ;
+ public void sendWord(String word) ;
+ public void sendControl(char character) ;
+ public void sendNumber(long number) ;
+
+ public void startTuple() ;
+ public void endTuple() ;
+
+ public void flush() ;
+}
Added: jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStreamWrapper.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStreamWrapper.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStreamWrapper.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStreamWrapper.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,67 @@
+/*
+ * 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.riot.tio;
+
+import org.apache.jena.riot.tokens.Token ;
+
+import com.hp.hpl.jena.graph.Node ;
+
+
+public class TokenOutputStreamWrapper implements TokenOutputStream
+{
+ private TokenOutputStream stream ;
+
+ public TokenOutputStreamWrapper(TokenOutputStream stream)
+ {
+ this.stream = stream ;
+ }
+
+ @Override
+ public void startTuple() { stream.startTuple() ; }
+
+ @Override
+ public void endTuple() { stream.endTuple() ; }
+
+ @Override
+ public void sendToken(Token token) { stream.sendToken(token) ; }
+
+ @Override
+ public void sendControl(char character) { stream.sendControl(character) ; }
+
+ @Override
+ public void sendNode(Node node) { stream.sendNode(node) ; }
+
+ @Override
+ public void sendNumber(long number) { stream.sendNumber(number) ; }
+
+ @Override
+ public void sendString(String string) { stream.sendString(string) ; }
+
+ @Override
+ public void sendWord(String word) { stream.sendWord(word) ; }
+
+ @Override
+ public void close() { stream.close(); }
+
+ @Override
+ public void flush() { stream.flush(); }
+
+ @Override
+ public void sync() { stream.sync() ; }
+}
Added: jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStreamWriter.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStreamWriter.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStreamWriter.java (added)
+++ jena/Experimental/rdfpatch/src/main/java/org/apache/jena/riot/tio/TokenOutputStreamWriter.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,414 @@
+/*
+ * 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.riot.tio;
+
+import java.io.IOException ;
+import java.io.Writer ;
+import java.util.ArrayList ;
+import java.util.List ;
+
+import org.apache.jena.atlas.io.AWriter ;
+import org.apache.jena.atlas.io.BufferingWriter ;
+import org.apache.jena.atlas.io.IO ;
+import org.apache.jena.riot.RiotException ;
+import org.apache.jena.riot.out.NodeFormatter ;
+import org.apache.jena.riot.out.NodeFormatterTTL ;
+import org.apache.jena.riot.system.PrefixMap ;
+import org.apache.jena.riot.system.PrefixMapFactory ;
+import org.apache.jena.riot.tokens.Token ;
+import org.apache.jena.riot.tokens.TokenizerText ;
+import org.slf4j.Logger ;
+import org.slf4j.LoggerFactory ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.sparql.util.FmtUtils ;
+
+public class TokenOutputStreamWriter implements TokenOutputStream
+{
+ // Both token output stream and tuple abbreviation rules.
+ // Separate out abbreviation/LastTuple support?
+
+ // Will need rework to improve performance.
+ // XXX TokenWriter. See tokenToString
+
+ private static Logger log = LoggerFactory.getLogger(TokenOutputStreamWriter.class) ;
+
+ // Whether to space out the tuples a bit for readability.
+ private static final boolean GAPS = true ;
+
+ private final AWriter out ;
+ private List<Object> lastTuple = null ;
+ private boolean inTuple = false ;
+ private boolean inSection = false ;
+ private List<Object> thisTuple = new ArrayList<Object> () ;
+
+ private final PrefixMap pmap = PrefixMapFactory.create() ;
+ private final NodeFormatter fmt ;
+
+ private String label ;
+
+ /** Create a TokenOutputStreamWriter going to a Writer,
+ * ideally one that buffers (e.g. {@linkplain BufferingWriter}).
+ * @param out
+ */
+ public TokenOutputStreamWriter(Writer out) {
+ this(null, null, out) ;
+ }
+
+ /** Create a TokenOutputStreamWriter going to a Writer,
+ * ideally one that buffers (e.g. {@linkplain BufferingWriter}).
+ * @param out
+ */
+ public TokenOutputStreamWriter(AWriter out) {
+ this(null, null, out) ;
+ }
+
+ /** Create a TokenOutputStreamWriter going to a Writer,
+ * with a given NodeFormatter policy
+ * ideally one that buffers (e.g. {@linkplain BufferingWriter}).
+ * @param out
+ */
+ public TokenOutputStreamWriter(NodeFormatter formatter, Writer out) {
+ this(null, formatter, out) ;
+ }
+
+ /** Create a TokenOutputStreamWriter going to a Writer,
+ * with a given NodeFormatter policy
+ * ideally one that buffers (e.g. {@linkplain BufferingWriter}).
+ * @param out
+ */
+ public TokenOutputStreamWriter(NodeFormatter formatter, AWriter out) {
+ this(null, formatter, out) ;
+ }
+
+ public TokenOutputStreamWriter(String label, NodeFormatter formatter, Writer out)
+ { this(label, formatter, IO.wrap(out)) ; }
+
+ public TokenOutputStreamWriter(String label, NodeFormatter formatter, AWriter out)
+ {
+ if ( formatter == null )
+ // XXX Must write bNodes as <_:....>
+ formatter = new NodeFormatterTTL(null, pmap) ;
+ formatter = new NodeFormatterBNode(formatter) ;
+
+ this.fmt = formatter ;
+ this.out = out ;
+ this.label = label ;
+ }
+
+ static class NodeFormatterBNode extends NodeFormatterWrapper {
+ public NodeFormatterBNode(NodeFormatter other) {
+ super(other) ;
+ }
+ @Override
+ public void format(AWriter w, Node n)
+ {
+ if ( n.isBlank() )
+ formatBNode(w, n) ;
+ else
+ super.format(w, n);
+ }
+
+ @Override
+ public void formatBNode(AWriter w, Node n)
+ { formatBNode(w, n.getBlankNodeLabel()); }
+
+ @Override
+ public void formatBNode(AWriter w, String label)
+ {
+ w.print("<_:");
+ w.print(label) ;
+ w.print(">");
+ }
+ }
+
+ static class NodeFormatterWrapper implements NodeFormatter {
+ private final NodeFormatter fmt ;
+
+ public NodeFormatterWrapper(NodeFormatter other)
+ { this.fmt = other ; }
+
+ @Override
+ public void format(AWriter w, Node n)
+ { fmt.format(w, n); }
+
+ @Override
+ public void formatURI(AWriter w, Node n)
+ { fmt.formatURI(w, n); }
+
+ @Override
+ public void formatURI(AWriter w, String uriStr)
+ { fmt.formatURI(w, uriStr); }
+
+ @Override
+ public void formatVar(AWriter w, Node n)
+ { fmt.formatVar(w, n); }
+
+ @Override
+ public void formatVar(AWriter w, String name)
+ { fmt.formatVar(w, name); }
+
+ @Override
+ public void formatBNode(AWriter w, Node n)
+ { fmt.formatBNode(w, n); }
+
+ @Override
+ public void formatBNode(AWriter w, String label)
+ { fmt.formatBNode(w, label); }
+
+ @Override
+ public void formatLiteral(AWriter w, Node n)
+ { fmt.formatLiteral(w, n); }
+
+ @Override
+ public void formatLitString(AWriter w, String lex)
+ { fmt.formatLitString(w, lex); }
+
+ @Override
+ public void formatLitLang(AWriter w, String lex, String langTag)
+ { fmt.formatLitLang(w, lex, langTag); }
+
+ @Override
+ public void formatLitDT(AWriter w, String lex, String datatypeURI)
+ { fmt.formatLitDT(w, lex, datatypeURI); }
+
+ }
+ // Really want to directly insert in to the output byte buffer.
+ // Optimization for later - get something working for now
+ // (and it may well be fast enough anyway).
+
+ public void setPrefixMapping(String prefix, String uri)
+ {
+ String pf = prefix ;
+ if ( pf.endsWith(":") )
+ pf = pf.substring(0, pf.length()-1) ;
+ else
+ prefix = prefix + ":" ;
+ if ( pmap != null )
+ pmap.add(pf, uri) ;
+ startTuple() ;
+ lastTuple = null ;
+ write("@prefix") ;
+ gap(true) ;
+ write(prefix) ;
+ gap(true) ;
+ write("<") ;
+ write(uri) ;
+ write(">") ;
+ gap(false) ;
+ endTuple() ;
+ }
+
+ @Override
+ public void sendToken(Token token)
+ {
+ remember(token) ;
+ String string = tokenToString(token) ;
+ write(string) ;
+ gap(true) ;
+ }
+
+ @Override
+ public void sendNode(Node node)
+ {
+ remember(node) ;
+ fmt.format(out, node);
+ gap(false) ;
+ }
+
+ @Override
+ public void sendString(String string)
+ {
+ remember(string) ;
+ fmt.formatLitString(out, string);
+ gap(false) ;
+ }
+
+ @Override
+ public void sendWord(String string)
+ {
+ remember(string) ;
+ write(string) ; // no escapes, no quotes
+ gap(true) ;
+ }
+
+ private static String cntrlAsString(char cntrl)
+ {
+ return Character.toString((char)TokenizerText.CTRL_CHAR)+Character.toString(cntrl);
+ }
+
+ @Override
+ public void sendControl(char controlChar)
+ {
+ String x = cntrlAsString(controlChar) ;
+ remember(x) ;
+ write(x) ;
+ gap(false) ;
+ }
+
+ @Override
+ public void sendNumber(long number)
+ {
+ remember(number) ;
+ write(Long.toString(number)) ;
+ gap(true) ;
+ }
+
+ @Override
+ public void startTuple()
+ {
+ // Ensure endTuple.
+ if ( log.isDebugEnabled() ) log.debug("Start tuple") ;
+ }
+
+ @Override
+ public void endTuple()
+ {
+ if ( ! inTuple ) return ;
+ write(".") ;
+ write("\n") ;
+ if ( log.isDebugEnabled() )
+ {
+ log.debug("End tuple") ;
+ if ( label != null )
+ log.debug(">> "+label+": "+thisTuple) ;
+ else
+ log.debug(">> "+thisTuple.toString()) ;
+ }
+
+ // Compression.
+ lastTuple = thisTuple ;
+ thisTuple = new ArrayList<Object>(lastTuple.size()) ;
+ inTuple = false ;
+ }
+
+ @Override
+ public void close()
+ {
+ if ( inTuple ) {}
+ IO.close(out);
+ }
+
+ @Override
+ public void sync()
+ { flush() ; }
+
+ @Override
+ public void flush() {
+ out.flush() ;
+ }
+
+ // --------
+
+ private String tokenToString(Token token)
+ {
+ switch ( token.getType() )
+ {
+ // superclass case NODE:
+ case IRI:
+ return "<"+token.getImage()+">" ;
+ case PREFIXED_NAME:
+ notImplemented(token) ;
+ return null ;
+ case BNODE:
+ return "_:"+token.getImage() ;
+ //BOOLEAN,
+ // One kind of string?
+ case STRING:
+ case STRING1:
+ case STRING2:
+ case LONG_STRING1:
+ case LONG_STRING2:
+ // XXX
+ //return "'"+NodeFmtLib.esc(token.getImage())+"'" ;
+ return "\""+FmtUtils.stringEsc(token.getImage())+"\"" ;
+ case LITERAL_LANG:
+ return "\""+FmtUtils.stringEsc(token.getImage())+"\"@"+token.getImage2() ;
+ case LITERAL_DT:
+ return "\""+FmtUtils.stringEsc(token.getImage())+"\"^^"+tokenToString(token.getSubToken2()) ;
+ case INTEGER:
+ case DECIMAL:
+ case DOUBLE:
+ return token.getImage() ;
+
+ // Not RDF
+ case KEYWORD:
+ return token.getImage() ;
+ case CNTRL:
+ if ( token.getCntrlCode() == -1 )
+ return "*" ;
+ return "*"+Character.toString((char)token.getCntrlCode()) ;
+ case VAR:
+ case HEX:
+
+ // Syntax
+ // COLON is only visible if prefix names are not being processed.
+ case DOT:
+ case COMMA:
+ case SEMICOLON:
+ case COLON:
+ case DIRECTIVE:
+ // LT, GT, LE, GE are only visible if IRI processing is not enabled.
+ case LT:
+ case GT:
+ case LE:
+ case GE:
+ // In RDF, UNDERSCORE is only visible if BNode processing is not enabled.
+ case UNDERSCORE:
+ case LBRACE: case RBRACE: // {}
+ case LPAREN: case RPAREN: // ()
+ case LBRACKET: case RBRACKET: // []
+
+ case PLUS:
+ case MINUS:
+ case STAR:
+ case SLASH:
+ case RSLASH:
+ default:
+ notImplemented(token) ;
+ return null ;
+ //case EOF:
+ }
+ }
+
+ private void remember(Object obj)
+ { thisTuple.add(obj) ; }
+
+ // A gap is always necessary for items that are not endLog-limited.
+ // For example, numbers adjacent to numbers must have a gap but
+ // quoted string then quoted string does not require a gap.
+ private void gap(boolean required)
+ {
+ if ( required || GAPS ) write(" ") ;
+ }
+
+ // Beware of multiple stringing.
+ private void write(String string)
+ {
+ //System.out.println("Send: "+string) ;
+ inTuple = true ;
+ out.write(string) ;
+ }
+
+ private static void exception(IOException ex)
+ { throw new CommsException(ex) ; }
+
+ private void notImplemented(Token token)
+ { throw new RiotException("Unencodable token: "+token) ; }
+}
Added: jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TS_RDFPatch.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TS_RDFPatch.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TS_RDFPatch.java (added)
+++ jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TS_RDFPatch.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,30 @@
+/**
+ * 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.rdfpatch;
+
+import org.junit.runner.RunWith ;
+import org.junit.runners.Suite ;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses( {
+ TestRDFPatch.class
+ , TestPatchPlayer.class
+})
+
+public class TS_RDFPatch { }
Added: jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TestPatchPlayer.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TestPatchPlayer.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TestPatchPlayer.java (added)
+++ jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TestPatchPlayer.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,140 @@
+/**
+ * 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.rdfpatch;
+
+import java.io.ByteArrayInputStream ;
+import java.io.ByteArrayOutputStream ;
+import java.util.List ;
+
+import org.apache.jena.atlas.io.IO ;
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.After ;
+import org.junit.Before ;
+import org.junit.Test ;
+
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphFactory ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphMonitor ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+import com.hp.hpl.jena.sparql.sse.SSE ;
+
+public class TestPatchPlayer extends BaseTest {
+
+ DatasetGraph dsg1 = DatasetGraphFactory.createMem() ;
+ ByteArrayOutputStream bout = new ByteArrayOutputStream() ;
+ DatasetGraphMonitor dsg = RDFPatch.recordChanges(dsg1, bout) ;
+
+ @Before public void beforeTest() {}
+ @After public void afterTest() {}
+
+ private static Quad quad1 = SSE.parseQuad("(:g _:s <p> 1)") ;
+ private static Quad quad2 = SSE.parseQuad("(:g _:s <p> 2)") ;
+
+ private DatasetGraph replay() {
+ DatasetChangesTuples tuples = (DatasetChangesTuples)dsg.getMonitor() ;
+ IO.close(bout) ;
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()) ;
+ DatasetGraph dsg2 = DatasetGraphFactory.createMem() ;
+ RDFPatch.replayChanges(dsg2, bin);
+ return dsg2 ;
+ }
+
+ private static void check(DatasetGraph dsg, Quad...quads) {
+ if ( quads.length == 0 ) {
+ assertTrue(dsg.isEmpty()) ;
+ return ;
+ }
+
+ List<Quad> list = Iter.toList(dsg.find()) ;
+ assertEquals(list.size(), quads.length) ;
+
+ for (Quad q : quads ) {
+ assertTrue(dsg.contains(q)) ;
+ }
+ }
+
+ @Test public void record_00() {
+ DatasetGraph dsg2 = replay() ;
+ check(dsg2) ;
+ }
+
+ @Test public void record_add() {
+ dsg.getMonitor().start() ;
+ dsg.add(quad1) ;
+ dsg.getMonitor().finish() ;
+ DatasetGraph dsg2 = replay() ;
+ check(dsg2, quad1) ;
+ }
+
+ @Test public void record_add_add_1() {
+ dsg.getMonitor().start() ;
+ dsg.add(quad1) ;
+ dsg.add(quad2) ;
+ dsg.getMonitor().finish() ;
+ DatasetGraph dsg2 = replay() ;
+ check(dsg2, quad1, quad2) ;
+ }
+
+ @Test public void record_add_add_2() {
+ dsg.getMonitor().start() ;
+ dsg.add(quad1) ;
+ dsg.add(quad1) ;
+ dsg.getMonitor().finish() ;
+ DatasetGraph dsg2 = replay() ;
+ check(dsg2, quad1) ;
+ }
+
+ @Test public void record_add_delete_1() {
+ dsg.getMonitor().start() ;
+ dsg.add(quad1) ;
+ dsg.delete(quad1) ;
+ dsg.getMonitor().finish() ;
+ DatasetGraph dsg2 = replay() ;
+ check(dsg2) ;
+ }
+
+ @Test public void record_add_delete_2() {
+ dsg.getMonitor().start() ;
+ dsg.add(quad1) ;
+ dsg.delete(quad2) ;
+ dsg.getMonitor().finish() ;
+ DatasetGraph dsg2 = replay() ;
+ check(dsg2, quad1) ;
+ }
+
+ @Test public void record_add_delete_3() {
+ dsg.getMonitor().start() ;
+ dsg.delete(quad2) ;
+ dsg.add(quad1) ;
+ dsg.getMonitor().finish() ;
+ DatasetGraph dsg2 = replay() ;
+ check(dsg2, quad1) ;
+ }
+
+ @Test public void record_add_delete_4() {
+ dsg.getMonitor().start() ;
+ dsg.delete(quad1) ;
+ dsg.add(quad1) ;
+ dsg.getMonitor().finish() ;
+ DatasetGraph dsg2 = replay() ;
+ check(dsg2, quad1) ;
+ }
+
+}
Added: jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TestRDFPatch.java
URL: http://svn.apache.org/viewvc/jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TestRDFPatch.java?rev=1555594&view=auto
==============================================================================
--- jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TestRDFPatch.java (added)
+++ jena/Experimental/rdfpatch/src/test/java/org/apache/jena/rdfpatch/TestRDFPatch.java Sun Jan 5 18:05:50 2014
@@ -0,0 +1,301 @@
+/**
+ * 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.rdfpatch;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+
+import com.hp.hpl.jena.query.ReadWrite ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.DatasetGraphFactory ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+import com.hp.hpl.jena.sparql.sse.SSE ;
+
+public class TestRDFPatch extends BaseTest
+{
+ private static DatasetGraphPatchTransaction create(Quad...quads) {
+ DatasetGraph dsg1 = DatasetGraphFactory.createMem() ;
+ for ( Quad quad : quads )
+ dsg1.add(quad) ;
+ DatasetGraphPatchTransaction dsg = new DatasetGraphPatchTransaction(dsg1) ;
+ return dsg ;
+ }
+
+ private static Quad quad1 = SSE.parseQuad("(:g <s> <p> _:a)") ;
+
+ @Test
+ public void patch_01() {
+ DatasetGraphPatchTransaction dsg = create() ;
+ dsg.begin(ReadWrite.WRITE) ;
+ try {
+ dsg.commit() ;
+ } finally {
+ dsg.end() ;
+ }
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertTrue(dsg.isEmpty()) ;
+ } finally { dsg.end() ; }
+ }
+
+ @Test
+ public void patch_02() {
+ DatasetGraphPatchTransaction dsg = create() ;
+ dsg.begin(ReadWrite.WRITE) ;
+ try {
+ dsg.abort() ;
+ } finally {
+ dsg.end() ;
+ }
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertTrue(dsg.isEmpty()) ;
+ } finally { dsg.end() ; }
+ }
+
+ @Test public void patch_add_commit() {
+ DatasetGraphPatchTransaction dsg = create() ;
+ dsg.begin(ReadWrite.WRITE);
+ dsg.add(quad1) ;
+ assertFalse(dsg.isEmpty()) ;
+ dsg.commit() ;
+ dsg.end();
+
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertFalse(dsg.isEmpty()) ;
+ assertTrue(dsg.contains(quad1)) ;
+ } finally { dsg.end() ; }
+ }
+
+ @Test public void patch_add_abort() {
+ DatasetGraphPatchTransaction dsg = create() ;
+ dsg.begin(ReadWrite.WRITE);
+ dsg.add(quad1) ;
+ assertFalse(dsg.isEmpty()) ;
+ dsg.abort() ;
+ dsg.end();
+
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertTrue(dsg.isEmpty()) ;
+ assertFalse(dsg.contains(quad1)) ;
+ } finally { dsg.end() ; }
+ }
+
+ @Test public void patch_add_add_commit() {
+ DatasetGraphPatchTransaction dsg = create() ;
+ dsg.begin(ReadWrite.WRITE);
+ dsg.add(quad1) ;
+ dsg.add(quad1) ;
+ assertFalse(dsg.isEmpty()) ;
+ dsg.commit() ;
+ dsg.end();
+
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertFalse(dsg.isEmpty()) ;
+ assertTrue(dsg.contains(quad1)) ;
+ } finally { dsg.end() ; }
+ }
+
+ @Test public void patch_add_add_abort() {
+ DatasetGraphPatchTransaction dsg = create() ;
+ dsg.begin(ReadWrite.WRITE);
+ dsg.add(quad1) ;
+ dsg.add(quad1) ;
+ assertFalse(dsg.isEmpty()) ;
+ dsg.abort() ;
+ dsg.end();
+
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertTrue(dsg.isEmpty()) ;
+ assertFalse(dsg.contains(quad1)) ;
+ } finally { dsg.end() ; }
+ }
+
+
+ @Test public void patch_add_delete_commit() {
+ DatasetGraphPatchTransaction dsg = create() ;
+ dsg.begin(ReadWrite.WRITE);
+ dsg.add(quad1) ;
+ dsg.delete(quad1) ;
+ assertTrue(dsg.isEmpty()) ;
+ dsg.commit() ;
+ dsg.end();
+
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertTrue(dsg.isEmpty()) ;
+ assertFalse(dsg.contains(quad1)) ;
+ } finally { dsg.end() ; }
+ }
+
+ @Test public void patch_add_delete_abort() {
+ DatasetGraphPatchTransaction dsg = create() ;
+ dsg.begin(ReadWrite.WRITE);
+ dsg.add(quad1) ;
+ dsg.delete(quad1) ;
+ assertTrue(dsg.isEmpty()) ;
+ dsg.abort() ;
+ dsg.end();
+
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertTrue(dsg.isEmpty()) ;
+ assertFalse(dsg.contains(quad1)) ;
+ } finally { dsg.end() ; }
+ }
+
+ @Test public void patch_delete_add_commit() {
+ DatasetGraphPatchTransaction dsg = create() ;
+ dsg.begin(ReadWrite.WRITE);
+ dsg.delete(quad1) ;
+ dsg.add(quad1) ;
+ assertFalse(dsg.isEmpty()) ;
+ dsg.commit() ;
+ dsg.end();
+
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertFalse(dsg.isEmpty()) ;
+ assertTrue(dsg.contains(quad1)) ;
+ } finally { dsg.end() ; }
+ }
+
+ @Test public void patch_delete_add_abort() {
+ DatasetGraphPatchTransaction dsg = create() ;
+ dsg.begin(ReadWrite.WRITE);
+ dsg.delete(quad1) ;
+ dsg.add(quad1) ;
+ assertFalse(dsg.isEmpty()) ;
+ dsg.abort() ;
+ dsg.end();
+
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertTrue(dsg.isEmpty()) ;
+ assertFalse(dsg.contains(quad1)) ;
+ } finally { dsg.end() ; }
+ }
+
+ @Test public void patch_add_delete_add_commit() {
+ DatasetGraphPatchTransaction dsg = create() ;
+ dsg.begin(ReadWrite.WRITE);
+ dsg.add(quad1) ;
+ dsg.delete(quad1) ;
+ dsg.add(quad1) ;
+ assertFalse(dsg.isEmpty()) ;
+ dsg.commit() ;
+ dsg.end();
+
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertFalse(dsg.isEmpty()) ;
+ assertTrue(dsg.contains(quad1)) ;
+ } finally { dsg.end() ; }
+ }
+
+ @Test public void patch_add_delete_add_abort() {
+ DatasetGraphPatchTransaction dsg = create() ;
+ dsg.begin(ReadWrite.WRITE);
+ dsg.add(quad1) ;
+ dsg.delete(quad1) ;
+ dsg.add(quad1) ;
+ assertFalse(dsg.isEmpty()) ;
+ dsg.abort() ;
+ dsg.end();
+
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertTrue(dsg.isEmpty()) ;
+ assertFalse(dsg.contains(quad1)) ;
+ } finally { dsg.end() ; }
+ }
+
+
+ @Test public void patch_delete_01() {
+ DatasetGraphPatchTransaction dsg = create(quad1) ;
+ assertTrue(dsg.contains(quad1)) ;
+
+ dsg.begin(ReadWrite.WRITE);
+ dsg.delete(quad1) ;
+ assertTrue(dsg.isEmpty()) ;
+ dsg.commit() ;
+ dsg.end();
+
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertTrue(dsg.isEmpty()) ;
+ assertFalse(dsg.contains(quad1)) ;
+ } finally { dsg.end() ; }
+ }
+
+ @Test public void patch_delete_02() {
+ DatasetGraphPatchTransaction dsg = create(quad1) ;
+ assertTrue(dsg.contains(quad1)) ;
+
+ dsg.begin(ReadWrite.WRITE);
+ dsg.delete(quad1) ;
+ assertTrue(dsg.isEmpty()) ;
+ dsg.commit() ;
+ dsg.end();
+
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertTrue(dsg.isEmpty()) ;
+ assertFalse(dsg.contains(quad1)) ;
+ } finally { dsg.end() ; }
+ }
+
+ @Test public void patch_delete_03() {
+ DatasetGraphPatchTransaction dsg = create() ;
+ assertFalse(dsg.contains(quad1)) ;
+
+ dsg.begin(ReadWrite.WRITE);
+ dsg.delete(quad1) ;
+ assertTrue(dsg.isEmpty()) ;
+ dsg.commit() ;
+ dsg.end();
+
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertTrue(dsg.isEmpty()) ;
+ assertFalse(dsg.contains(quad1)) ;
+ } finally { dsg.end() ; }
+ }
+
+ @Test public void patch_delete_04() {
+ DatasetGraphPatchTransaction dsg = create() ;
+ assertFalse(dsg.contains(quad1)) ;
+
+ dsg.begin(ReadWrite.WRITE);
+ dsg.delete(quad1) ;
+ assertTrue(dsg.isEmpty()) ;
+ dsg.commit() ;
+ dsg.end();
+
+ dsg.begin(ReadWrite.READ) ;
+ try {
+ assertTrue(dsg.isEmpty()) ;
+ assertFalse(dsg.contains(quad1)) ;
+ } finally { dsg.end() ; }
+ }
+}