You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commonsrdf.apache.org by st...@apache.org on 2016/09/28 13:51:53 UTC

[01/36] incubator-commonsrdf git commit: More source() docs

Repository: incubator-commonsrdf
Updated Branches:
  refs/heads/master 9782a5860 -> e0d319181


More source() docs


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/dcf43835
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/dcf43835
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/dcf43835

Branch: refs/heads/master
Commit: dcf43835742e90dcc7668b5ecaca44415e4bbc23
Parents: 4aacf85
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Sun Mar 27 21:47:26 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Apr 1 16:19:58 2016 +0100

----------------------------------------------------------------------
 .../commons/rdf/api/RDFParserBuilder.java       | 120 ++++++++++++++++---
 1 file changed, 105 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/dcf43835/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index 2cc60bb..3bf536d 100644
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -145,15 +145,15 @@ public interface RDFParserBuilder {
 	 * <code>@base</code> in Turtle documents).
 	 * <p>
 	 * If the source is in a syntax that does not support relative IRI
-	 * references, e.g. {@link RDFSyntax#NTRIPLES}, setting the base has no
-	 * effect.
+	 * references (e.g. {@link RDFSyntax#NTRIPLES}), setting the 
+	 * <code>base</code> has no effect.
 	 * <p>
 	 * This method will override any base IRI set with {@link #base(String)}.
 	 *
 	 * @see #base(String)
 	 * @param base
-	 *            An absolute IRI to use as a base
-	 * @return An {@link RDFParserBuilder} that will use the specified base IRI
+	 *            An absolute IRI to use as a base.
+	 * @return An {@link RDFParserBuilder} that will use the specified base IRI.
 	 */
 	RDFParserBuilder base(IRI base);
 
@@ -166,37 +166,41 @@ public interface RDFParserBuilder {
 	 * <code>@base</code> in Turtle documents).
 	 * <p>
 	 * If the source is in a syntax that does not support relative IRI
-	 * references, e.g. {@link RDFSyntax#NTRIPLES}, setting the base has no
-	 * effect.
+	 * references (e.g. {@link RDFSyntax#NTRIPLES}), setting the 
+	 * <code>base</code> has no effect.
 	 * <p>
 	 * This method will override any base IRI set with {@link #base(IRI)}.
 	 *
 	 * @see #base(IRI)
 	 * @param base
-	 *            An absolute IRI to use as a base
-	 * @return An {@link RDFParserBuilder} that will use the specified base IRI
+	 *            An absolute IRI to use as a base.
+	 * @return An {@link RDFParserBuilder} that will use the specified base IRI.
 	 */
 	RDFParserBuilder base(String base);
 
 	/**
-	 * Specify a source to parse.
+	 * Specify a source {@link InputStream} to parse.
 	 * <p>
 	 * The source set will not be read before the call to {@link #parse()}.
 	 * <p>
 	 * The InputStream will not be closed after parsing. The InputStream does
-	 * not need to support {@link InputStream#markSupported()}. The parser might
-	 * not consume the complete stream (e.g. the parser may not read beyond the
-	 * closing tag of <code>&lt;/rdf:Description&;gt</code>).
+	 * not need to support {@link InputStream#markSupported()}. 
+	 * <p>
+	 * The parser might
+	 * not consume the complete stream (e.g. an RDF/XML parser may not read beyond the
+	 * closing tag of <code>&lt;/rdf:Description&gt;</code>).
 	 * <p>
 	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)}
 	 * SHOULD be set before calling {@link #parse()}.
 	 * <p>
 	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
-	 * the {@link #contentType(String)} specifies otherwise.
+	 * the {@link #contentType(String)} specifies otherwise or the document
+	 * declares its own charset (e.g. RDF/XML with a 
+	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
 	 * <p>
 	 * The {@link #base(IRI)} or {@link #base(String)} MUST be set before
-	 * calling {@link #parse()}, unless the syntax does not permit relative
-	 * IRIs.
+	 * calling {@link #parse()}, unless the RDF syntax does not permit relative
+	 * IRIs (e.g. {@link RDFSyntax#NTRIPLES}).
 	 * <p>
 	 * This method will override any source set with {@link #source(IRI)},
 	 * {@link #source(Path)} or {@link #source(String)}.
@@ -207,10 +211,96 @@ public interface RDFParserBuilder {
 	 */
 	RDFParserBuilder source(InputStream inputStream);
 
+	/**
+	 * Specify a source file {@link Path} to parse.
+	 * <p>
+	 * The source set will not be read before the call to {@link #parse()}.
+	 * <p>
+	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)}
+	 * SHOULD be set before calling {@link #parse()}. 
+	 * <p>
+	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
+	 * the {@link #contentType(String)} specifies otherwise or the document
+	 * declares its own charset (e.g. RDF/XML with a 
+	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
+	 * <p>
+	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before
+	 * calling {@link #parse()}, otherwise {@link Path#toUri()} will be used
+	 * as the base IRI.
+	 * <p>
+	 * This method will override any source set with {@link #source(IRI)},
+	 * {@link #source(InputStream)} or {@link #source(String)}.
+	 * 
+	 * @param file
+	 *            A Path for a file to parse
+	 * @return An {@link RDFParserBuilder} that will use the specified source.
+	 */
 	RDFParserBuilder source(Path file);
 
+	/**
+	 * Specify an absolute source {@link IRI} to retrieve and parse.
+	 * <p>
+	 * The source set will not be read before the call to {@link #parse()}.
+	 * <p>
+	 * If this builder does not support the given IRI 
+	 * (e.g. <code>urn:uuid:ce667463-c5ab-4c23-9b64-701d055c4890</code>),
+	 * this method should succeed, while the {@link #parse()} should 
+	 * throw an {@link IOException}. 
+	 * <p>
+	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)}
+	 * MAY be set before calling {@link #parse()}, in which case that
+	 * type MAY be used for content negotiation (e.g. <code>Accept</code> header in HTTP),
+	 * and SHOULD be used for selecting the RDFSyntax.
+	 * <p>
+	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
+	 * the protocol's equivalent of <code>Content-Type</code> specifies otherwise or
+	 * the document declares its own charset (e.g. RDF/XML with a 
+	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
+	 * <p>
+	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before
+	 * calling {@link #parse()}, otherwise the source IRI will be used
+	 * as the base IRI.
+	 * <p>
+	 * This method will override any source set with {@link #source(Path)},
+	 * {@link #source(InputStream)} or {@link #source(String)}.
+	 * 
+	 * @param iri
+	 *            An IRI to retrieve and parse
+	 * @return An {@link RDFParserBuilder} that will use the specified source.
+	 */
 	RDFParserBuilder source(IRI iri);
 
+	/**
+	 * Specify an absolute source IRI to retrieve and parse.
+	 * <p>
+	 * The source set will not be read before the call to {@link #parse()}.
+	 * <p>
+	 * If this builder does not support the given IRI 
+	 * (e.g. <code>urn:uuid:ce667463-c5ab-4c23-9b64-701d055c4890</code>),
+	 * this method should succeed, while the {@link #parse()} should 
+	 * throw an {@link IOException}. 
+	 * <p>
+	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)}
+	 * MAY be set before calling {@link #parse()}, in which case that
+	 * type MAY be used for content negotiation (e.g. <code>Accept</code> header in HTTP),
+	 * and SHOULD be used for selecting the RDFSyntax.
+	 * <p>
+	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
+	 * the protocol's equivalent of <code>Content-Type</code> specifies otherwise or
+	 * the document declares its own charset (e.g. RDF/XML with a 
+	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
+	 * <p>
+	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before
+	 * calling {@link #parse()}, otherwise the source IRI will be used
+	 * as the base IRI.
+	 * <p>
+	 * This method will override any source set with {@link #source(Path)},
+	 * {@link #source(InputStream)} or {@link #source(IRI)}.
+	 * 
+	 * @param iri
+	 *            An IRI to retrieve and parse
+	 * @return An {@link RDFParserBuilder} that will use the specified source.
+	 */	
 	RDFParserBuilder source(String iri);
 
 	/**


[17/36] incubator-commonsrdf git commit: Merge branch 'master' into parser-writer-interface

Posted by st...@apache.org.
Merge branch 'master' into parser-writer-interface


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/dc7589fa
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/dc7589fa
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/dc7589fa

Branch: refs/heads/master
Commit: dc7589fa454ce0401c7576052ddacda269b07f6b
Parents: 13a6b07 73994db
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Mon Apr 4 15:50:31 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Mon Apr 4 15:50:31 2016 +0100

----------------------------------------------------------------------
 .travis.yml                                     |  2 -
 .../apache/commons/rdf/api/RDFTermFactory.java  | 12 +++---
 .../commons/rdf/api/AbstractGraphTest.java      | 42 +++++++-------------
 .../commons/rdf/simple/SimpleGraphTest.java     | 17 ++++++++
 4 files changed, 38 insertions(+), 35 deletions(-)
----------------------------------------------------------------------



[11/36] incubator-commonsrdf git commit: Some AbstractRDFParserBuilder tests

Posted by st...@apache.org.
Some AbstractRDFParserBuilder tests


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/528af997
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/528af997
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/528af997

Branch: refs/heads/master
Commit: 528af9976ce03280578f82531a95a49a3546b238
Parents: 478b20e
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Sun Apr 3 01:47:16 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Sun Apr 3 02:32:47 2016 +0100

----------------------------------------------------------------------
 .../simple/AbstractRDFParserBuilderTest.java    | 220 +++++++++++++++++--
 .../rdf/simple/DummyRDFParserBuilder.java       |  70 ++++--
 2 files changed, 250 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/528af997/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java
----------------------------------------------------------------------
diff --git a/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java b/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java
index 1b751fa..d23e1c8 100644
--- a/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java
+++ b/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java
@@ -19,9 +19,11 @@ package org.apache.commons.rdf.simple;
 
 import static org.junit.Assert.*;
 
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.commons.rdf.api.Graph;
@@ -29,39 +31,211 @@ import org.apache.commons.rdf.api.IRI;
 import org.apache.commons.rdf.api.Literal;
 import org.apache.commons.rdf.api.RDFParserBuilder;
 import org.apache.commons.rdf.api.RDFSyntax;
+import org.apache.commons.rdf.api.RDFTerm;
+import org.apache.commons.rdf.api.RDFTermFactory;
 import org.apache.commons.rdf.api.Triple;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 public class AbstractRDFParserBuilderTest {
 
-	/**
-	 * Test a basic parsing of an N-Triples-file
-	 * 
-	 * @throws Exception
-	 */
-	@Test
-	public void parseFile() throws Exception {		
-		Path file = Files.createTempFile("test", ".nt");
-		// No need to populate the file as the dummy parser
+	private RDFTermFactory factory = new SimpleRDFTermFactory();
+	
+	private DummyRDFParserBuilder dummyParser = new DummyRDFParserBuilder();
+	private Path testNt;
+	private Path testTtl;
+	private Path testXml;
+
+	@Before
+	public void createTempFile() throws IOException {
+		testNt = Files.createTempFile("test", ".nt");
+		testTtl = Files.createTempFile("test", ".ttl");
+		testXml = Files.createTempFile("test", ".xml");
+
+		// No need to populate the files as the dummy parser
 		// doesn't actually read anything
-		
-		RDFParserBuilder parser = new DummyRDFParserBuilder()
-				.source(file).contentType(RDFSyntax.NTRIPLES);
-		Future<Graph> f = parser.parse();
-		Graph g = f.get(5, TimeUnit.SECONDS);
-		
-		assertEquals(1, g.size());
-		Triple triple = g.getTriples().findAny().get();
+	}
+
+	@After
+	public void deleteTempFiles() throws IOException {
+		Files.deleteIfExists(testNt);
+		Files.deleteIfExists(testTtl);
+		Files.deleteIfExists(testXml);
+	}
+
+	@Test
+	public void guessRDFSyntax() throws Exception {
+		assertEquals(RDFSyntax.NTRIPLES, AbstractRDFParserBuilder.guessRDFSyntax(testNt).get());
+		assertEquals(RDFSyntax.TURTLE, AbstractRDFParserBuilder.guessRDFSyntax(testTtl).get());
+		assertFalse(AbstractRDFParserBuilder.guessRDFSyntax(testXml).isPresent());
+	}
+
+	private void checkGraph(Graph g) throws Exception {				
+		assertTrue(g.size() > 0);		
+		IRI greeting = factory.createIRI("http://example.com/greeting");	
+		// Should only have parsed once!
+		assertEquals(1, g.getTriples(null, greeting, null).count());
+		Triple triple = g.getTriples(null, greeting, null).findAny().get();
 		assertTrue(triple.getSubject() instanceof IRI);
-		IRI iri = (IRI)triple.getSubject();
-		assertEquals("http://example.com/test1", iri.getIRIString());
-		
+		IRI parsing = (IRI) triple.getSubject();
+		assertTrue(parsing.getIRIString().startsWith("urn:uuid:"));
+
 		assertEquals("http://example.com/greeting", triple.getPredicate().getIRIString());
-		
+
 		assertTrue(triple.getObject() instanceof Literal);
-		Literal literal = (Literal)triple.getObject();
+		Literal literal = (Literal) triple.getObject();
 		assertEquals("Hello world", literal.getLexicalForm());
 		assertFalse(literal.getLanguageTag().isPresent());
 		assertEquals(Types.XSD_STRING, literal.getDatatype());
+		
+		// Check uniqueness of properties that are always present
+		assertEquals(1, 
+				g.getTriples(null, factory.createIRI("http://example.com/source"), null).count());
+		
+		// Check optional properties that are unique
+		assertTrue(2 > g.getTriples(null, factory.createIRI("http://example.com/base"), null).count());
+		assertTrue(2 > g.getTriples(null, factory.createIRI("http://example.com/contentType"), null).count());
+		assertTrue(2 > g.getTriples(null, factory.createIRI("http://example.com/contentTypeSyntax"), null).count());
+	}
+	
+	@Test
+	public void parseFile() throws Exception {
+		RDFParserBuilder parser = dummyParser.source(testNt);
+		Graph g = parser.parse().get(5, TimeUnit.SECONDS);
+		checkGraph(g);
+		// FIXME: this could potentially break if the equivalent of /tmp includes
+		// international characters
+		assertEquals("<" + testNt.toUri().toString() + ">", firstPredicate(g, "source"));
+		// Should be set to the file path
+		assertEquals("<" + testNt.toUri().toString() + ">", firstPredicate(g, "base"));		
+
+		// Should NOT have guessed the content type
+		assertNull(firstPredicate(g, "contentType"));
+		assertNull(firstPredicate(g, "contentTypeSyntax"));
+	}
+
+
+	@Test
+	public void parseNoSource() throws Exception {
+		thrown.expect(IllegalStateException.class);
+		dummyParser.parse();		
 	}
+	
+	@Test
+	public void parseBaseAndContentTypeNoSource() throws Exception {
+		// Can set the other options, even without source()
+		IRI base = dummyParser.createRDFTermFactory().createIRI("http://www.example.org/test.rdf");
+		RDFParserBuilder parser = dummyParser.base(base).contentType(RDFSyntax.RDFXML);
+		thrown.expect(IllegalStateException.class);
+		thrown.expectMessage("No source has been set");
+		// but .parse() should fail
+		parser.parse();		
+	}
+	
+	@Test
+	public void parseFileMissing() throws Exception {
+		Files.delete(testNt);
+		// This should not fail yet
+		RDFParserBuilder parser = dummyParser.source(testNt);
+		// but here:
+		thrown.expect(IOException.class);
+		parser.parse();		
+	}
+
+	
+	@Test
+	public void parseFileContentType() throws Exception {
+		RDFParserBuilder parser = dummyParser.source(testNt).contentType(RDFSyntax.NTRIPLES);
+		Graph g = parser.parse().get(5, TimeUnit.SECONDS);
+		checkGraph(g);
+		// FIXME: this could potentially break if the equivalent of /tmp includes
+		// international characters
+		assertEquals("<" + testNt.toUri().toString() + ">", firstPredicate(g, "source"));
+		assertEquals("<" + testNt.toUri().toString() + ">", firstPredicate(g, "base"));		
+		assertEquals("\"NTRIPLES\"", firstPredicate(g, "contentTypeSyntax"));
+		assertEquals("\"application/n-triples\"", firstPredicate(g, "contentType"));
+	}
+
+	private String firstPredicate(Graph g, String pred) {
+		return g.getTriples(null, factory.createIRI("http://example.com/" + pred), null)
+				.map(Triple::getObject).map(RDFTerm::ntriplesString).findAny().orElse(null);
+	}
+
+
+	@Rule
+	public ExpectedException thrown = ExpectedException.none();
+	
+	@Test
+	public void parseInputStreamFailsIfBaseMissing() throws Exception {
+		InputStream inputStream = new ByteArrayInputStream(new byte[0]);
+		// Should not fail at this point
+		RDFParserBuilder parser = dummyParser.source(inputStream);
+		// but here:
+		thrown.expect(IllegalStateException.class);
+		thrown.expectMessage("base iri required for inputstream source");
+		parser.parse();
+	}
+
+	@Test
+	public void parseInputStreamWithBase() throws Exception {
+		InputStream inputStream = new ByteArrayInputStream(new byte[0]);
+		IRI base = dummyParser.createRDFTermFactory().createIRI("http://www.example.org/test.rdf");
+		RDFParserBuilder parser = dummyParser.source(inputStream).base(base);		
+		Graph g = parser.parse().get(5, TimeUnit.SECONDS);
+		checkGraph(g);
+		assertEquals("<http://www.example.org/test.rdf>", firstPredicate(g, "base"));
+		// in our particular debug output, 
+		// bnode source indicates InputStream 
+		assertTrue(firstPredicate(g, "source").startsWith("_:"));
+		assertNull(firstPredicate(g, "contentType"));
+		assertNull(firstPredicate(g, "contentTypeSyntax"));
+	}
+	
+	@Test
+	public void parseInputStreamWithNQuads() throws Exception {
+		InputStream inputStream = new ByteArrayInputStream(new byte[0]);
+		RDFParserBuilder parser = dummyParser.source(inputStream).contentType(RDFSyntax.NQUADS);		
+		Graph g = parser.parse().get(5, TimeUnit.SECONDS);
+		checkGraph(g);
+		assertNull(firstPredicate(g, "base"));
+		// in our particular debug output, 
+		// bnode source indicates InputStream 
+		assertTrue(firstPredicate(g, "source").startsWith("_:"));
+		assertEquals("\"application/n-quads\"", firstPredicate(g, "contentType"));
+		assertEquals("\"NQUADS\"", firstPredicate(g, "contentTypeSyntax"));
+	}	
+
+	@Test
+	public void parseIRI() throws Exception {
+		IRI iri = dummyParser.createRDFTermFactory().createIRI("http://www.example.net/test.ttl");
+		RDFParserBuilder parser = dummyParser.source(iri);		
+		Graph g = parser.parse().get(5, TimeUnit.SECONDS);
+		checkGraph(g);
+		assertEquals("<http://www.example.net/test.ttl>", firstPredicate(g, "source"));
+		// No base - assuming the above IRI is always 
+		// the base would break server-supplied base from 
+		// any HTTP Location redirects and  Content-Location header
+		assertNull(firstPredicate(g, "base"));
+		// ".ttl" in IRI string does not imply any content type
+		assertNull(firstPredicate(g, "contentType"));
+		assertNull(firstPredicate(g, "contentTypeSyntax"));
+		
+	}
+	
+	@Test
+	public void parseIRIBaseContentType() throws Exception {
+		IRI iri = dummyParser.createRDFTermFactory().createIRI("http://www.example.net/test.ttl");
+		RDFParserBuilder parser = dummyParser.source(iri).base(iri).contentType(RDFSyntax.TURTLE);
+		Graph g = parser.parse().get(5, TimeUnit.SECONDS);
+		checkGraph(g);
+		assertEquals("<http://www.example.net/test.ttl>", firstPredicate(g, "source"));
+		assertEquals("<http://www.example.net/test.ttl>", firstPredicate(g, "base"));
+		assertEquals("\"TURTLE\"", firstPredicate(g, "contentTypeSyntax"));
+		assertEquals("\"text/turtle\"", firstPredicate(g, "contentType"));
+	}
+
+	
 }

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/528af997/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java b/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
index 38e6ed2..ddaf4ed 100644
--- a/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
+++ b/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
@@ -19,42 +19,78 @@ package org.apache.commons.rdf.simple;
 
 import java.io.IOException;
 import java.text.ParseException;
+import java.util.UUID;
 
 import org.apache.commons.rdf.api.Graph;
 import org.apache.commons.rdf.api.IRI;
-import org.apache.commons.rdf.api.Literal;
 import org.apache.commons.rdf.api.RDFParserBuilder;
 import org.apache.commons.rdf.api.RDFTermFactory;
 
 /** 
- * For test purposes - a {@link RDFParserBuilder} that always insert a single triple.
+ * For test purposes - a {@link RDFParserBuilder} that inserts information
+ * about what it has been asked to parse instead of actually parsing anything.
  * <p>
- * This dummy RDF parser always sleeps for at least 1000 ms
- * before inserting the triple:
+ * This always insert at least the triple equivalent to:
  * <pre>
- *    <http://example.com/test1> <http://example.com/greeting> "Hello world" .
+ *    <urn:uuid:b7ac3fcc-4d86-4d28-8358-a1cd094974a6> <http://example.com/greeting> "Hello world" .
  * </pre>
+ * Additional triples match the corresponding getter in AbstractRDFParserBuilder,
+ * e.g.:
+ * <pre>
+ *   <urn:uuid:b7ac3fcc-4d86-4d28-8358-a1cd094974a6> <http://example.com/base> <http://www.example.org/> .
+ *   <urn:uuid:b7ac3fcc-4d86-4d28-8358-a1cd094974a6> <http://example.com/sourceFile> "/tmp/file.ttl" .   
+ * </pre> 
+ * 
  *
  */
 public class DummyRDFParserBuilder extends AbstractRDFParserBuilder {
-
+	
 	@Override
 	protected void parseSynchronusly() throws IOException, IllegalStateException, ParseException {		
 		// From parseSynchronusly both of these are always present
 		RDFTermFactory factory = getRdfTermFactory().get();
 		Graph graph = getIntoGraph().get();
+				
+		// well - each parsing is unique. This should hopefully
+		// catch any accidental double parsing
+		IRI parsing = factory.createIRI("urn:uuid:" + UUID.randomUUID());
+		graph.add(parsing, factory.createIRI("http://example.com/greeting"), 
+				factory.createLiteral("Hello world"));
 		
-		// Let's always insert the same triple
-		IRI test1 = factory.createIRI("http://example.com/test1");
-		IRI greeting = factory.createIRI("http://example.com/greeting");
-		Literal hello = factory.createLiteral("Hello world");
-		try {
-			// Pretend we take a while to parse
-			Thread.sleep(1000);			
-		} catch (InterruptedException e) {
-			return;
-		} 
-		graph.add(test1, greeting, hello); 		
+		// Now we'll expose the finalized AbstractRDFParserBuilder settings
+		// so they can be inspected by the junit test
+
+		if (getSourceIri().isPresent()) {
+			graph.add(parsing, 
+					factory.createIRI("http://example.com/source"),
+					getSourceIri().get());			
+		}		
+		if (getSourceFile().isPresent()) {
+			graph.add(parsing, 
+					factory.createIRI("http://example.com/source"),
+					factory.createIRI(getSourceFile().get().toUri().toString()));
+		}
+		if (getSourceInputStream().isPresent()) { 
+			graph.add(parsing, 
+					factory.createIRI("http://example.com/source"),
+					factory.createBlankNode());
+		}
+
+		if (getBase().isPresent()) { 
+			graph.add(parsing, 
+					factory.createIRI("http://example.com/base"),
+					getBase().get());
+		}
+		if (getContentType().isPresent()) {
+			graph.add(parsing, 
+					factory.createIRI("http://example.com/contentType"),
+					factory.createLiteral(getContentType().get()));
+		}
+		if (getContentTypeSyntax().isPresent()) {
+			graph.add(parsing, 
+					factory.createIRI("http://example.com/contentTypeSyntax"),
+					factory.createLiteral(getContentTypeSyntax().get().name()));
+		}		
 	}
 
 }


[06/36] incubator-commonsrdf git commit: RDFParserBuilder javadoc on exceptions

Posted by st...@apache.org.
RDFParserBuilder javadoc on exceptions


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/6f1f669a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/6f1f669a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/6f1f669a

Branch: refs/heads/master
Commit: 6f1f669a38a05e61d40cbbfd1572e0127244669b
Parents: 5e41513
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Mon Mar 28 02:06:16 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Apr 1 16:19:59 2016 +0100

----------------------------------------------------------------------
 .../commons/rdf/api/RDFParserBuilder.java       | 32 +++++++++++++++-----
 1 file changed, 24 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/6f1f669a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index 3a853f5..6d2d1d0 100644
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -109,11 +109,11 @@ public interface RDFParserBuilder {
 	 *            or <code>text/turtle;charset="UTF-8"</code> as specified by
 	 *            <a href="https://tools.ietf.org/html/rfc7231#section-3.1.1.1">
 	 *            RFC7231</a>.
+	 * @return An {@link RDFParserBuilder} that will use the specified content
+	 *         type.
 	 * @throws IllegalArgumentException
 	 *             If the contentType has an invalid syntax, or this
 	 *             RDFParserBuilder does not support the specified contentType.
-	 * @return An {@link RDFParserBuilder} that will use the specified content
-	 *         type.
 	 */
 	RDFParserBuilder contentType(String contentType);
 
@@ -171,8 +171,10 @@ public interface RDFParserBuilder {
 	 * @param base
 	 *            An absolute IRI to use as a base.
 	 * @return An {@link RDFParserBuilder} that will use the specified base IRI.
+	 * @throws IllegalArgumentException
+	 *             If the base is not a valid absolute IRI string
 	 */
-	RDFParserBuilder base(String base);
+	RDFParserBuilder base(String base) throws IllegalArgumentException;
 
 	/**
 	 * Specify a source {@link InputStream} to parse.
@@ -294,8 +296,11 @@ public interface RDFParserBuilder {
 	 * @param iri
 	 *            An IRI to retrieve and parse
 	 * @return An {@link RDFParserBuilder} that will use the specified source.
+	 * @throws IllegalArgumentException
+	 *             If the base is not a valid absolute IRI string
+	 * 
 	 */
-	RDFParserBuilder source(String iri);
+	RDFParserBuilder source(String iri) throws IllegalArgumentException;
 
 	/**
 	 * Parse the specified source.
@@ -319,12 +324,23 @@ public interface RDFParserBuilder {
 	 * <p>
 	 * If {@link #intoGraph(Graph)} has been specified, this SHOULD be the same
 	 * {@link Graph} instance returned from {@link Future#get() once parsing has
-	 * completed.
+	 * completed successfully.
+	 * <p>
+	 * If an exception occurs during parsing, (e.g. {@link IOException} or
+	 * {@link java.text.ParseException}, it should be indicated as the
+	 * {@link java.util.concurrent.ExecutionException#getCause()) in the
+	 * {@link java.util.concurrent.ExecutionException) thrown on
+	 * {@link Future#get()}.
 	 * 
-	 * @return A Future that will return the populated graph when the parsing
-	 *         has finished.
+	 * @return A Future that will return the populated {@link Graph} when the
+	 *         parsing has finished.
 	 * @throws IOException
-	 *             If an error occurred while reading the source.
+	 *             If an error occurred while starting to read the source (e.g.
+	 *             file not found, unsupported IRI protocol). Note that IO
+	 *             errors during parsing would instead be the
+	 *             {@link java.util.concurrent.ExecutionException#getCause()) of
+	 *             the {@link java.util.concurrent.ExecutionException) thrown on
+	 *             {@link Future#get()}.
 	 * @throws IllegalStateException
 	 *             If the builder is in an invalid state, e.g. a
 	 *             <code>source</code> has not been set.


[33/36] incubator-commonsrdf git commit: Corrected javadoc syntax/links

Posted by st...@apache.org.
Corrected javadoc syntax/links


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/bfcead4f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/bfcead4f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/bfcead4f

Branch: refs/heads/master
Commit: bfcead4f8ac403686cf136a59c598b07d6526a33
Parents: 7201668
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Tue Sep 13 00:08:44 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Tue Sep 13 00:11:20 2016 +0100

----------------------------------------------------------------------
 .../apache/commons/rdf/simple/AbstractRDFParserBuilder.java    | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/bfcead4f/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
index 0dc0e67..9e97487 100644
--- a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
@@ -369,10 +369,6 @@ public abstract class AbstractRDFParserBuilder<T extends AbstractRDFParserBuilde
 	 * One of the source fields MUST be present, as checked by {@link #checkSource()}.
 	 * <p>
 	 * {@link #checkBaseRequired()} is called to verify if {@link #getBase()} is required.
-	 * <p>
-	 * When this method is called, {@link #intoGraph} MUST always be present, as
-	 * that is where the parsed triples MUST be inserted into.
-	 * <p>
 	 * 
 	 * @throws IOException If the source could not be read 
 	 * @throws RDFParseException If the source could not be parsed (e.g. a .ttl file was not valid Turtle)
@@ -384,7 +380,7 @@ public abstract class AbstractRDFParserBuilder<T extends AbstractRDFParserBuilde
 	 * completed.
 	 * <p>
 	 * The returned clone will always have
-	 * {@link #getIntoGraph()} and {@link #getRdfTermFactory()} present.
+	 * {@link #getTarget()} and {@link #getRdfTermFactory()} present.
 	 * <p>
 	 * If the {@link #getSourceFile()} is present, but the 
 	 * {@link #getBase()} is not present, the base will be set to the


[07/36] incubator-commonsrdf git commit: about asynchronous stuff

Posted by st...@apache.org.
about asynchronous stuff


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/5e41513a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/5e41513a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/5e41513a

Branch: refs/heads/master
Commit: 5e41513aaa4a5f71e979a65a7e221e64cf7cd4d1
Parents: dcf4383
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Sun Mar 27 21:57:18 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Apr 1 16:19:59 2016 +0100

----------------------------------------------------------------------
 .../commons/rdf/api/RDFParserBuilder.java       | 118 +++++++++++--------
 1 file changed, 66 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/5e41513a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index 3bf536d..3a853f5 100644
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -29,9 +29,8 @@ import java.util.concurrent.Future;
  * This interface follows the
  * <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder pattern</a>,
  * allowing to set parser settings like {@link #contentType(RDFSyntax)} and
- * {@link #base(IRI)}. A caller MUST call one of the
- * {@link #source(IRI)} methods before calling {@link #parse()} on the returned
- * RDFParserBuilder.
+ * {@link #base(IRI)}. A caller MUST call one of the {@link #source(IRI)}
+ * methods before calling {@link #parse()} on the returned RDFParserBuilder.
  * <p>
  * It is undefined if a RDFParserBuilder is mutable or thread-safe, so callers
  * should always use the returned modified RDFParserBuilder from the builder
@@ -98,9 +97,8 @@ public interface RDFParserBuilder {
 	 * any <code>Content-Type</code> headers or equivalent.
 	 * <p>
 	 * The content type MAY include a <code>charset</code> parameter if the RDF
-	 * media types permit it; the default charset 
-	 * is {@link StandardCharsets#UTF_8} unless overridden within the
-	 * document.
+	 * media types permit it; the default charset is
+	 * {@link StandardCharsets#UTF_8} unless overridden within the document.
 	 * <p>
 	 * This method will override any contentType set with
 	 * {@link #contentType(RDFSyntax)}.
@@ -112,9 +110,8 @@ public interface RDFParserBuilder {
 	 *            <a href="https://tools.ietf.org/html/rfc7231#section-3.1.1.1">
 	 *            RFC7231</a>.
 	 * @throws IllegalArgumentException
-	 *             If the contentType has an invalid syntax, 
-	 *             or this RDFParserBuilder does not support the specified
-	 *             contentType.
+	 *             If the contentType has an invalid syntax, or this
+	 *             RDFParserBuilder does not support the specified contentType.
 	 * @return An {@link RDFParserBuilder} that will use the specified content
 	 *         type.
 	 */
@@ -125,9 +122,8 @@ public interface RDFParserBuilder {
 	 * <p>
 	 * The default (if this option has not been set) is that each call to
 	 * {@link #parse()} return a new {@link Graph}, which is created using
-	 * {@link RDFTermFactory#createGraph()} 
-	 * if {@link #rdfTermFactory(RDFTermFactory)}
-	 * has been set.
+	 * {@link RDFTermFactory#createGraph()} if
+	 * {@link #rdfTermFactory(RDFTermFactory)} has been set.
 	 * 
 	 * @param graph
 	 *            The {@link Graph} to add triples into.
@@ -145,7 +141,7 @@ public interface RDFParserBuilder {
 	 * <code>@base</code> in Turtle documents).
 	 * <p>
 	 * If the source is in a syntax that does not support relative IRI
-	 * references (e.g. {@link RDFSyntax#NTRIPLES}), setting the 
+	 * references (e.g. {@link RDFSyntax#NTRIPLES}), setting the
 	 * <code>base</code> has no effect.
 	 * <p>
 	 * This method will override any base IRI set with {@link #base(String)}.
@@ -166,7 +162,7 @@ public interface RDFParserBuilder {
 	 * <code>@base</code> in Turtle documents).
 	 * <p>
 	 * If the source is in a syntax that does not support relative IRI
-	 * references (e.g. {@link RDFSyntax#NTRIPLES}), setting the 
+	 * references (e.g. {@link RDFSyntax#NTRIPLES}), setting the
 	 * <code>base</code> has no effect.
 	 * <p>
 	 * This method will override any base IRI set with {@link #base(IRI)}.
@@ -184,18 +180,18 @@ public interface RDFParserBuilder {
 	 * The source set will not be read before the call to {@link #parse()}.
 	 * <p>
 	 * The InputStream will not be closed after parsing. The InputStream does
-	 * not need to support {@link InputStream#markSupported()}. 
+	 * not need to support {@link InputStream#markSupported()}.
 	 * <p>
-	 * The parser might
-	 * not consume the complete stream (e.g. an RDF/XML parser may not read beyond the
-	 * closing tag of <code>&lt;/rdf:Description&gt;</code>).
+	 * The parser might not consume the complete stream (e.g. an RDF/XML parser
+	 * may not read beyond the closing tag of
+	 * <code>&lt;/rdf:Description&gt;</code>).
 	 * <p>
 	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)}
 	 * SHOULD be set before calling {@link #parse()}.
 	 * <p>
 	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
 	 * the {@link #contentType(String)} specifies otherwise or the document
-	 * declares its own charset (e.g. RDF/XML with a 
+	 * declares its own charset (e.g. RDF/XML with a
 	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
 	 * <p>
 	 * The {@link #base(IRI)} or {@link #base(String)} MUST be set before
@@ -217,16 +213,16 @@ public interface RDFParserBuilder {
 	 * The source set will not be read before the call to {@link #parse()}.
 	 * <p>
 	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)}
-	 * SHOULD be set before calling {@link #parse()}. 
+	 * SHOULD be set before calling {@link #parse()}.
 	 * <p>
 	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
 	 * the {@link #contentType(String)} specifies otherwise or the document
-	 * declares its own charset (e.g. RDF/XML with a 
+	 * declares its own charset (e.g. RDF/XML with a
 	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
 	 * <p>
-	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before
-	 * calling {@link #parse()}, otherwise {@link Path#toUri()} will be used
-	 * as the base IRI.
+	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before calling
+	 * {@link #parse()}, otherwise {@link Path#toUri()} will be used as the base
+	 * IRI.
 	 * <p>
 	 * This method will override any source set with {@link #source(IRI)},
 	 * {@link #source(InputStream)} or {@link #source(String)}.
@@ -242,24 +238,23 @@ public interface RDFParserBuilder {
 	 * <p>
 	 * The source set will not be read before the call to {@link #parse()}.
 	 * <p>
-	 * If this builder does not support the given IRI 
-	 * (e.g. <code>urn:uuid:ce667463-c5ab-4c23-9b64-701d055c4890</code>),
-	 * this method should succeed, while the {@link #parse()} should 
-	 * throw an {@link IOException}. 
+	 * If this builder does not support the given IRI (e.g.
+	 * <code>urn:uuid:ce667463-c5ab-4c23-9b64-701d055c4890</code>), this method
+	 * should succeed, while the {@link #parse()} should throw an
+	 * {@link IOException}.
 	 * <p>
-	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)}
-	 * MAY be set before calling {@link #parse()}, in which case that
-	 * type MAY be used for content negotiation (e.g. <code>Accept</code> header in HTTP),
+	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)} MAY
+	 * be set before calling {@link #parse()}, in which case that type MAY be
+	 * used for content negotiation (e.g. <code>Accept</code> header in HTTP),
 	 * and SHOULD be used for selecting the RDFSyntax.
 	 * <p>
 	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
-	 * the protocol's equivalent of <code>Content-Type</code> specifies otherwise or
-	 * the document declares its own charset (e.g. RDF/XML with a 
+	 * the protocol's equivalent of <code>Content-Type</code> specifies
+	 * otherwise or the document declares its own charset (e.g. RDF/XML with a
 	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
 	 * <p>
-	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before
-	 * calling {@link #parse()}, otherwise the source IRI will be used
-	 * as the base IRI.
+	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before calling
+	 * {@link #parse()}, otherwise the source IRI will be used as the base IRI.
 	 * <p>
 	 * This method will override any source set with {@link #source(Path)},
 	 * {@link #source(InputStream)} or {@link #source(String)}.
@@ -275,24 +270,23 @@ public interface RDFParserBuilder {
 	 * <p>
 	 * The source set will not be read before the call to {@link #parse()}.
 	 * <p>
-	 * If this builder does not support the given IRI 
-	 * (e.g. <code>urn:uuid:ce667463-c5ab-4c23-9b64-701d055c4890</code>),
-	 * this method should succeed, while the {@link #parse()} should 
-	 * throw an {@link IOException}. 
+	 * If this builder does not support the given IRI (e.g.
+	 * <code>urn:uuid:ce667463-c5ab-4c23-9b64-701d055c4890</code>), this method
+	 * should succeed, while the {@link #parse()} should throw an
+	 * {@link IOException}.
 	 * <p>
-	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)}
-	 * MAY be set before calling {@link #parse()}, in which case that
-	 * type MAY be used for content negotiation (e.g. <code>Accept</code> header in HTTP),
+	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)} MAY
+	 * be set before calling {@link #parse()}, in which case that type MAY be
+	 * used for content negotiation (e.g. <code>Accept</code> header in HTTP),
 	 * and SHOULD be used for selecting the RDFSyntax.
 	 * <p>
 	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
-	 * the protocol's equivalent of <code>Content-Type</code> specifies otherwise or
-	 * the document declares its own charset (e.g. RDF/XML with a 
+	 * the protocol's equivalent of <code>Content-Type</code> specifies
+	 * otherwise or the document declares its own charset (e.g. RDF/XML with a
 	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
 	 * <p>
-	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before
-	 * calling {@link #parse()}, otherwise the source IRI will be used
-	 * as the base IRI.
+	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before calling
+	 * {@link #parse()}, otherwise the source IRI will be used as the base IRI.
 	 * <p>
 	 * This method will override any source set with {@link #source(Path)},
 	 * {@link #source(InputStream)} or {@link #source(IRI)}.
@@ -300,15 +294,35 @@ public interface RDFParserBuilder {
 	 * @param iri
 	 *            An IRI to retrieve and parse
 	 * @return An {@link RDFParserBuilder} that will use the specified source.
-	 */	
+	 */
 	RDFParserBuilder source(String iri);
 
 	/**
 	 * Parse the specified source.
+	 * <p>
+	 * A source method (e.g. {@link #source(InputStream)}, {@link #source(IRI)},
+	 * {@link #source(Path)}, {@link #source(String)} or an equivalent subclass
+	 * method) MUST have been called before calling this method, otherwise an
+	 * {@link IllegalStateException} will be thrown.
+	 * <p>
+	 * It is undefined if this method is thread-safe, however the
+	 * {@link RDFParserBuilder} may be reused (e.g. setting a different source)
+	 * as soon as the {@link Future} has been returned from this method.
+	 * <p>
+	 * The RDFParserBuilder SHOULD perform the parsing as an asynchronous
+	 * operation, and return the {@link Future} as soon as preliminary checks
+	 * (such as validity of the {@link #source(IRI)} and
+	 * {@link #contentType(RDFSyntax)} settings) have finished. The future
+	 * SHOULD not mark {@link Future#isDone()} before parsing is complete. A
+	 * synchronous implementation MAY be blocking on the <code>parse()</code>
+	 * call and return a Future that is already {@link Future#isDone()}.
+	 * <p>
+	 * If {@link #intoGraph(Graph)} has been specified, this SHOULD be the same
+	 * {@link Graph} instance returned from {@link Future#get() once parsing has
+	 * completed.
 	 * 
-	 * @return A Future that will return the graph containing (at least) the
-	 *         parsed triples.
-	 * 
+	 * @return A Future that will return the populated graph when the parsing
+	 *         has finished.
 	 * @throws IOException
 	 *             If an error occurred while reading the source.
 	 * @throws IllegalStateException


[26/36] incubator-commonsrdf git commit: Only Quad consumer, not Triple consumer

Posted by st...@apache.org.
Only Quad consumer, not Triple consumer


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/ddc545e5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/ddc545e5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/ddc545e5

Branch: refs/heads/master
Commit: ddc545e511ef9c8459ea5ce81fab750b4cd0a3b0
Parents: 953e9b8
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Mon Jun 20 09:56:51 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Mon Jun 20 09:56:51 2016 +0100

----------------------------------------------------------------------
 api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java | 2 --
 1 file changed, 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/ddc545e5/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index 5e8ee33..0494502 100644
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -191,8 +191,6 @@ public interface RDFParserBuilder {
 		});
 	}
 
-	RDFParserBuilder target(Consumer<Triple> tripleConsumer);
-	
 	/**
 	 * Specify a {@link Dataset} to add parsed quads to.
 	 * <p>


[21/36] incubator-commonsrdf git commit: Quad-support for RDFParserBuildler

Posted by st...@apache.org.
Quad-support for RDFParserBuildler

This changes intoGraph() to target(?)

where ? can be a Graph, Dataset or Consumer<Quad>

similarly parse() returns a Future<ParseResult> rather than
Future<Graph> - as there might not be any Graph


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/defdbd91
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/defdbd91
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/defdbd91

Branch: refs/heads/master
Commit: defdbd9160561ae93e8558a8f2c6cc27507b22bb
Parents: bb90a6e
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Wed Apr 13 16:50:31 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Wed Apr 13 16:50:31 2016 +0100

----------------------------------------------------------------------
 .../commons/rdf/api/RDFParserBuilder.java       | 174 ++++++++++++++-----
 .../rdf/simple/AbstractRDFParserBuilder.java    |  61 ++++---
 .../simple/AbstractRDFParserBuilderTest.java    |  40 +++--
 .../rdf/simple/DummyRDFParserBuilder.java       |  34 ++--
 4 files changed, 209 insertions(+), 100 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/defdbd91/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index 1425263..0494502 100644
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -22,58 +22,71 @@ import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
 import java.util.concurrent.Future;
+import java.util.function.Consumer;
 
 /**
- * Builder for parsing an RDF source into a Graph.
+ * Builder for parsing an RDF source into a target (e.g. a Graph/Dataset).
  * <p>
  * This interface follows the
  * <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder pattern</a>,
  * allowing to set parser settings like {@link #contentType(RDFSyntax)} and
  * {@link #base(IRI)}. A caller MUST call one of the <code>source</code> methods
  * (e.g. {@link #source(IRI)}, {@link #source(Path)},
- * {@link #source(InputStream)}) before calling {@link #parse()} on the returned
+ * {@link #source(InputStream)}), and MUST call one of the <code>target</code>
+ * methods (e.g. {@link #target(Consumer)}, {@link #target(Dataset)},
+ * {@link #target(Graph)}) before calling {@link #parse()} on the returned
  * RDFParserBuilder - however methods can be called in any order.
  * <p>
- * The call to {@link #parse()} returns a {@link Future}, allowing asynchronous parse
- * operations. This can be combined with {@link #intoGraph(Graph)}
- * allowing access to the graph before parsing has completed,
- * however callers are still recommended to to check 
- * {@link Future#get()} for any exceptions thrown during parsing.
+ * The call to {@link #parse()} returns a {@link Future}, allowing asynchronous
+ * parse operations. Callers are recommended to check {@link Future#get()} to
+ * ensure parsing completed successfully, or catch exceptions thrown during
+ * parsing.
  * <p>
  * Setting a method that has already been set will override any existing value
  * in the returned builder - irregardless of the parameter type (e.g.
  * {@link #source(IRI)} will override a previous {@link #source(Path)}. Settings
- * can be unset by passing <code>null</code> - this may require casting, e.g.
- * <code>contentType( (RDFSyntax) null )</code> to undo a previous call to
- * {@link #contentType(RDFSyntax)}.
+ * can be unset by passing <code>null</code> - note that this may 
+ * require casting, e.g. <code>contentType( (RDFSyntax) null )</code> 
+ * to undo a previous call to {@link #contentType(RDFSyntax)}.
  * <p>
  * It is undefined if a RDFParserBuilder is mutable or thread-safe, so callers
  * should always use the returned modified RDFParserBuilder from the builder
- * methods. The builder may return itself, or a cloned builder with the modified
- * settings applied. Implementations are however encouraged to be 
- * immutable and thread-safe and document this, 
- * as an example starting point, see 
+ * methods. The builder may return itself after modification, 
+ * or a cloned builder with the modified settings applied. 
+ * Implementations are however encouraged to be immutable,
+ * thread-safe and document this. As an example starting point, see
  * {@link org.apache.commons.rdf.simple.AbstractRDFParserBuilder}.
  * <p>
  * Example usage:
  * </p>
  * 
  * <pre>
- *   // Retrieve populated graph from the Future
- *   Graph g1 = ExampleRDFParserBuilder.source("http://example.com/graph.rdf").parse().get(30, TimeUnit.Seconds);
- *   // Or parsing into an existing Graph:
- *   ExampleRDFParserBuilder.source(Paths.get("/tmp/graph.ttl").contentType(RDFSyntax.TURTLE).intoGraph(g1).parse();
+ *   Graph g1 = rDFTermFactory.createGraph();
+ *   new ExampleRDFParserBuilder()
+ *    	.source(Paths.get("/tmp/graph.ttl"))
+ *    	.contentType(RDFSyntax.TURTLE)
+ *   	.target(g1)
+ *   	.parse().get(30, TimeUnit.Seconds);
  * </pre>
- * 
  *
  */
 public interface RDFParserBuilder {
 
+	/** 
+	 * The result of {@link RDFParserBuilder#parse()} indicating
+	 * parsing completed.
+	 * <p>
+	 * This is a marker interface that may be subclassed to include
+	 * parser details, e.g. warning messages or triple counts.
+	 */
+	public interface ParseResult {		
+	}
+
 	/**
 	 * Specify which {@link RDFTermFactory} to use for generating
 	 * {@link RDFTerm}s.
 	 * <p>
-	 * This option may be used together with {@link #intoGraph(Graph)} to
+	 * This option may be used together with {@link #target(Graph)} to
 	 * override the implementation's default factory and graph.
 	 * <p>
 	 * <strong>Warning:</strong> Using the same {@link RDFTermFactory} for 
@@ -82,7 +95,7 @@ public interface RDFParserBuilder {
 	 * use the {@link RDFTermFactory#createBlankNode(String)} method
 	 * from the parsed blank node labels.
 	 * 
-	 * @see #intoGraph(Graph)
+	 * @see #target(Graph)
 	 * @param rdfTermFactory
 	 *            {@link RDFTermFactory} to use for generating RDFTerms.
 	 * @return An {@link RDFParserBuilder} that will use the specified
@@ -144,30 +157,97 @@ public interface RDFParserBuilder {
 	RDFParserBuilder contentType(String contentType) throws IllegalArgumentException;
 
 	/**
-	 * Specify which {@link Graph} to add triples to.
-	 * <p>
-	 * The default (if this option has not been set) is that each call to
-	 * {@link #parse()} return a new {@link Graph}, which is created using
-	 * {@link RDFTermFactory#createGraph()} if
-	 * {@link #rdfTermFactory(RDFTermFactory)} has been set.
-	 * <p>
-	 * It is undefined if any triples are added to the specified
-	 * {@link Graph} if the {@link Future#get()} returned from 
-	 * {@link #parse()} throws any exceptions. (However 
-	 * implementations are free to prevent this using transaction 
-	 * mechanisms or similar).  However, if {@link Future#get()}
-	 * does not indicatean exception, the 
-	 * parser implementation SHOULD have inserted all parsed triples 
-	 * to the specified graph.
+	 * Specify a {@link Graph} to add parsed triples to.
+	 * <p>
+	 * If the source supports datasets (e.g. the {@link #contentType(RDFSyntax)}
+	 * set has {@link RDFSyntax#supportsDataset} is true)), then only quads in
+	 * the <em>default graph</em> will be added to the Graph as {@link Triple}s.
+	 * <p>
+	 * It is undefined if any triples are added to the specified {@link Graph}
+	 * if {@link #parse()} throws any exceptions. (However implementations are
+	 * free to prevent this using transaction mechanisms or similar). If
+	 * {@link Future#get()} does not indicate an exception, the parser
+	 * implementation SHOULD have inserted all parsed triples to the specified
+	 * graph.
+	 * <p>
+	 * Calling this method will override any earlier targets set with
+	 * {@link #target(Graph)}, {@link #target(Consumer)} or
+	 * {@link #target(Dataset)}.
+	 * <p>
+	 * The default implementation of this method calls {@link #target(Consumer)}
+	 * with a {@link Consumer} that does {@link Graph#add(Triple)} with
+	 * {@link Quad#asTriple()} if the quad is in the default graph.
 	 * 
 	 * @param graph
-	 *            The {@link Graph} to add triples into.
+	 *            The {@link Graph} to add triples to.
 	 * @return An {@link RDFParserBuilder} that will insert triples into the
 	 *         specified graph.
 	 */
-	RDFParserBuilder intoGraph(Graph graph);
+	default RDFParserBuilder target(Graph graph) {		
+		return target(q -> { 
+			if (! q.getGraphName().isPresent()) { 
+				graph.add(q.asTriple());
+			}
+		});
+	}
 
 	/**
+	 * Specify a {@link Dataset} to add parsed quads to.
+	 * <p>
+	 * It is undefined if any quads are added to the specified
+	 * {@link Dataset} if {@link #parse()} throws any exceptions. 
+	 * (However implementations are free to prevent this using transaction 
+	 * mechanisms or similar).  On the other hand, if {@link #parse()}
+	 * does not indicate an exception, the 
+	 * implementation SHOULD have inserted all parsed quads 
+	 * to the specified dataset.
+	 * <p>
+	 * Calling this method will override any earlier targets set with 
+	 * {@link #target(Graph)}, {@link #target(Consumer)} or {@link #target(Dataset)}.
+	 * <p>
+	 * The default implementation of this method calls {@link #target(Consumer)}
+	 * with a {@link Consumer} that does {@link Dataset#add(Quad)}.
+	 * 
+	 * @param dataset
+	 *            The {@link Dataset} to add quads to.
+	 * @return An {@link RDFParserBuilder} that will insert triples into the
+	 *         specified dataset.
+	 */
+	default RDFParserBuilder target(Dataset dataset) {
+		return target(dataset::add);
+	}
+
+	/**
+	 * Specify a consumer for parsed quads.
+	 * <p>
+	 * It is undefined if any quads are consumed if {@link #parse()} throws any
+	 * exceptions. On the other hand, if {@link #parse()} does not indicate an
+	 * exception, the implementation SHOULD have produced all parsed quads to
+	 * the specified consumer.
+	 * <p>
+	 * Calling this method will override any earlier targets set with
+	 * {@link #target(Graph)}, {@link #target(Consumer)} or
+	 * {@link #target(Dataset)}.
+	 * <p>
+	 * The consumer is not assumed to be thread safe - only one
+	 * {@link Consumer#accept(Object)} is delivered at a time for a given
+	 * {@link RDFParserBuilder#parse()} call.
+	 * <p>
+	 * This method is typically called with a functional consumer, for example:
+	 * <pre>
+	 * List<Quad> quads = new ArrayList<Quad>;
+	 * parserBuilder.target(quads::add).parse();
+	 * </pre>
+	 * 
+	 * @param consumer
+	 *            A {@link Consumer} of {@link Quad}s
+	 * @return An {@link RDFParserBuilder} that will call the consumer for into
+	 *         the specified dataset.
+	 * @return
+	 */
+	RDFParserBuilder target(Consumer<Quad> consumer);
+	
+	/**
 	 * Specify a base IRI to use for parsing any relative IRI references.
 	 * <p>
 	 * Setting this option will override any protocol-specific base IRI (e.g.
@@ -345,6 +425,11 @@ public interface RDFParserBuilder {
 	 * method) MUST have been called before calling this method, otherwise an
 	 * {@link IllegalStateException} will be thrown.
 	 * <p>
+	 * A target method (e.g. {@link #target(Consumer)}, {@link #target(Dataset)}
+	 * , {@link #target(Graph)} or an equivalent subclass method) MUST have been
+	 * called before calling this method, otherwise an
+	 * {@link IllegalStateException} will be thrown.
+	 * <p>
 	 * It is undefined if this method is thread-safe, however the
 	 * {@link RDFParserBuilder} may be reused (e.g. setting a different source)
 	 * as soon as the {@link Future} has been returned from this method.
@@ -357,12 +442,15 @@ public interface RDFParserBuilder {
 	 * synchronous implementation MAY be blocking on the <code>parse()</code>
 	 * call and return a Future that is already {@link Future#isDone()}.
 	 * <p>
-	 * If {@link #intoGraph(Graph)} has been specified, this SHOULD be the same
-	 * {@link Graph} instance returned from {@link Future#get()} once parsing has
-	 * completed successfully.
+	 * The returned {@link Future} contains a {@link ParseResult}. 
+	 * Implementations may subclass this interface to provide any 
+	 * parser details, e.g. list of warnings. <code>null</code> is a
+	 * possible return value if no details are available, but 
+	 * parsing succeeded.
 	 * <p>
 	 * If an exception occurs during parsing, (e.g. {@link IOException} or
-	 * {@link java.text.ParseException}), it should be indicated as the
+	 * {@link org.apache.commons.rdf.simple.AbstractRDFParserBuilder.RDFParseException}), 
+	 * it should be indicated as the
 	 * {@link java.util.concurrent.ExecutionException#getCause()} in the
 	 * {@link java.util.concurrent.ExecutionException} thrown on
 	 * {@link Future#get()}.
@@ -380,5 +468,5 @@ public interface RDFParserBuilder {
 	 *             If the builder is in an invalid state, e.g. a
 	 *             <code>source</code> has not been set.
 	 */
-	Future<Graph> parse() throws IOException, IllegalStateException;
+	Future<? extends ParseResult> parse() throws IOException, IllegalStateException;
 }

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/defdbd91/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
index ab37eef..9544928 100644
--- a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
@@ -26,9 +26,10 @@ import java.util.Optional;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
+import java.util.function.Consumer;
 
-import org.apache.commons.rdf.api.Graph;
 import org.apache.commons.rdf.api.IRI;
+import org.apache.commons.rdf.api.Quad;
 import org.apache.commons.rdf.api.RDFParserBuilder;
 import org.apache.commons.rdf.api.RDFSyntax;
 import org.apache.commons.rdf.api.RDFTermFactory;
@@ -111,15 +112,14 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	}
 
 	/**
-	 * Get the set {@link Graph} to insert into, if any.
+	 * Get the target to consume parsed Quads.
 	 * <p>
 	 * From the call to {@link #parseSynchronusly()}, this
-	 * method is always {@link Optional#isPresent()}
-	 * with a new {@link Graph} instance, and 
-	 * will be the value returned from {@link #parse()}.
+	 * method is always {@link Optional#isPresent()}.
+	 * 
 	 */	
-	public Optional<Graph> getIntoGraph() {
-		return intoGraph;
+	public Consumer<Quad> getTarget() {
+		return target;
 	}
 
 	/**
@@ -167,11 +167,11 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	private Optional<RDFTermFactory> rdfTermFactory = Optional.empty();
 	private Optional<RDFSyntax> contentTypeSyntax = Optional.empty();
 	private Optional<String> contentType = Optional.empty();
-	private Optional<Graph> intoGraph = Optional.empty();
 	private Optional<IRI> base = Optional.empty();
 	private Optional<InputStream> sourceInputStream = Optional.empty();
 	private Optional<Path> sourceFile = Optional.empty();
 	private Optional<IRI> sourceIri = Optional.empty();
+	private Consumer<Quad> target;
 
 	@Override
 	public AbstractRDFParserBuilder clone() {
@@ -206,13 +206,6 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	}
 
 	@Override
-	public RDFParserBuilder intoGraph(Graph graph) {
-		AbstractRDFParserBuilder c = clone();
-		c.intoGraph = Optional.ofNullable(graph);
-		return c;
-	}
-
-	@Override
 	public RDFParserBuilder base(IRI base) {
 		AbstractRDFParserBuilder c = clone();
 		c.base = Optional.ofNullable(base);
@@ -361,8 +354,10 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	 */
 	protected AbstractRDFParserBuilder prepareForParsing() throws IOException, IllegalStateException {
 		checkSource();
-		checkBaseRequired();
+		checkBaseRequired();		
 		checkContentType();
+		checkTarget();
+
 		// We'll make a clone of our current state which will be passed to
 		// parseSynchronously()
 		AbstractRDFParserBuilder c = clone();
@@ -371,10 +366,6 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 		if (!c.rdfTermFactory.isPresent()) {
 			c.rdfTermFactory = Optional.of(createRDFTermFactory());
 		}
-		// No graph? We'll create one.
-		if (!c.intoGraph.isPresent()) {
-			c.intoGraph = c.rdfTermFactory.map(RDFTermFactory::createGraph);
-		}
 		// sourceFile, but no base? Let's follow any symlinks and use
 		// the file:/// URI
 		if (c.sourceFile.isPresent() && !c.base.isPresent()) {
@@ -386,6 +377,19 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	}
 	
 	/**
+	 * Subclasses can override this method to check the target is 
+	 * valid.
+	 * <p>
+	 * The default implementation throws an IllegalStateException if the 
+	 * target has not been set.
+	 */
+	protected void checkTarget() {
+		if (target == null) {
+			throw new IllegalStateException("target has not been set");
+		}
+	}
+
+	/**
 	 * Subclasses can override this method to check compatibility with the
 	 * contentType setting.
 	 * 
@@ -441,13 +445,11 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	 * <p>
 	 * This is called by {@link #parse()} to set 
 	 * {@link #rdfTermFactory(RDFTermFactory)} if it is
-	 * {@link Optional#empty()}, and therefore used also for 
-	 * creating a new {@link Graph} if 
-	 * {@link #getIntoGraph()} is {@link Optional#empty()}.
+	 * {@link Optional#empty()}.
 	 * <p>
 	 * As parsed blank nodes might be made with 
 	 * {@link RDFTermFactory#createBlankNode(String)}, 
-	 * each call to this method should return 
+	 * each call to this method SHOULD return 
 	 * a new RDFTermFactory instance.
 	 * 
 	 * @return A new {@link RDFTermFactory}
@@ -457,12 +459,19 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	}
 
 	@Override
-	public Future<Graph> parse() throws IOException, IllegalStateException {
+	public Future<ParseResult> parse() throws IOException, IllegalStateException {
 		final AbstractRDFParserBuilder c = prepareForParsing();
 		return threadpool.submit(() -> {
 			c.parseSynchronusly();
-			return c.intoGraph.get();
+			return null;
 		});
 	}
 
+	@Override
+	public RDFParserBuilder target(Consumer<Quad> consumer) {
+		AbstractRDFParserBuilder c = clone();
+		c.target = consumer;
+		return c;
+	}
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/defdbd91/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java
----------------------------------------------------------------------
diff --git a/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java b/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java
index d23e1c8..439bacb 100644
--- a/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java
+++ b/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java
@@ -17,7 +17,10 @@
  */
 package org.apache.commons.rdf.simple;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
@@ -102,9 +105,10 @@ public class AbstractRDFParserBuilderTest {
 	}
 	
 	@Test
-	public void parseFile() throws Exception {
-		RDFParserBuilder parser = dummyParser.source(testNt);
-		Graph g = parser.parse().get(5, TimeUnit.SECONDS);
+	public void parseFile() throws Exception {	
+		Graph g = factory.createGraph();
+		RDFParserBuilder parser = dummyParser.source(testNt).target(g);
+		parser.parse().get(5, TimeUnit.SECONDS);
 		checkGraph(g);
 		// FIXME: this could potentially break if the equivalent of /tmp includes
 		// international characters
@@ -148,8 +152,12 @@ public class AbstractRDFParserBuilderTest {
 	
 	@Test
 	public void parseFileContentType() throws Exception {
-		RDFParserBuilder parser = dummyParser.source(testNt).contentType(RDFSyntax.NTRIPLES);
-		Graph g = parser.parse().get(5, TimeUnit.SECONDS);
+		Graph g = factory.createGraph();
+		RDFParserBuilder parser = dummyParser
+				.source(testNt)
+				.contentType(RDFSyntax.NTRIPLES)
+				.target(g);
+		parser.parse().get(5, TimeUnit.SECONDS);
 		checkGraph(g);
 		// FIXME: this could potentially break if the equivalent of /tmp includes
 		// international characters
@@ -183,8 +191,9 @@ public class AbstractRDFParserBuilderTest {
 	public void parseInputStreamWithBase() throws Exception {
 		InputStream inputStream = new ByteArrayInputStream(new byte[0]);
 		IRI base = dummyParser.createRDFTermFactory().createIRI("http://www.example.org/test.rdf");
-		RDFParserBuilder parser = dummyParser.source(inputStream).base(base);		
-		Graph g = parser.parse().get(5, TimeUnit.SECONDS);
+		Graph g = factory.createGraph();
+		RDFParserBuilder parser = dummyParser.source(inputStream).base(base).target(g);		
+		parser.parse().get(5, TimeUnit.SECONDS);
 		checkGraph(g);
 		assertEquals("<http://www.example.org/test.rdf>", firstPredicate(g, "base"));
 		// in our particular debug output, 
@@ -197,8 +206,9 @@ public class AbstractRDFParserBuilderTest {
 	@Test
 	public void parseInputStreamWithNQuads() throws Exception {
 		InputStream inputStream = new ByteArrayInputStream(new byte[0]);
-		RDFParserBuilder parser = dummyParser.source(inputStream).contentType(RDFSyntax.NQUADS);		
-		Graph g = parser.parse().get(5, TimeUnit.SECONDS);
+		Graph g = factory.createGraph();
+		RDFParserBuilder parser = dummyParser.source(inputStream).contentType(RDFSyntax.NQUADS).target(g);		
+		parser.parse().get(5, TimeUnit.SECONDS);
 		checkGraph(g);
 		assertNull(firstPredicate(g, "base"));
 		// in our particular debug output, 
@@ -211,8 +221,9 @@ public class AbstractRDFParserBuilderTest {
 	@Test
 	public void parseIRI() throws Exception {
 		IRI iri = dummyParser.createRDFTermFactory().createIRI("http://www.example.net/test.ttl");
-		RDFParserBuilder parser = dummyParser.source(iri);		
-		Graph g = parser.parse().get(5, TimeUnit.SECONDS);
+		Graph g = factory.createGraph();
+		RDFParserBuilder parser = dummyParser.source(iri).target(g);		
+		parser.parse().get(5, TimeUnit.SECONDS);
 		checkGraph(g);
 		assertEquals("<http://www.example.net/test.ttl>", firstPredicate(g, "source"));
 		// No base - assuming the above IRI is always 
@@ -228,8 +239,9 @@ public class AbstractRDFParserBuilderTest {
 	@Test
 	public void parseIRIBaseContentType() throws Exception {
 		IRI iri = dummyParser.createRDFTermFactory().createIRI("http://www.example.net/test.ttl");
-		RDFParserBuilder parser = dummyParser.source(iri).base(iri).contentType(RDFSyntax.TURTLE);
-		Graph g = parser.parse().get(5, TimeUnit.SECONDS);
+		Graph g = factory.createGraph();
+		RDFParserBuilder parser = dummyParser.source(iri).base(iri).contentType(RDFSyntax.TURTLE).target(g);
+		parser.parse().get(5, TimeUnit.SECONDS);
 		checkGraph(g);
 		assertEquals("<http://www.example.net/test.ttl>", firstPredicate(g, "source"));
 		assertEquals("<http://www.example.net/test.ttl>", firstPredicate(g, "base"));

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/defdbd91/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java b/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
index cc62f0c..0cb7093 100644
--- a/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
+++ b/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
@@ -18,11 +18,11 @@
 package org.apache.commons.rdf.simple;
 
 import java.io.IOException;
-import java.text.ParseException;
 import java.util.UUID;
+import java.util.function.Consumer;
 
-import org.apache.commons.rdf.api.Graph;
 import org.apache.commons.rdf.api.IRI;
+import org.apache.commons.rdf.api.Quad;
 import org.apache.commons.rdf.api.RDFParserBuilder;
 import org.apache.commons.rdf.api.RDFTermFactory;
 
@@ -49,47 +49,47 @@ public class DummyRDFParserBuilder extends AbstractRDFParserBuilder {
 	protected void parseSynchronusly() throws IOException, IllegalStateException, RDFParseException {		
 		// From parseSynchronusly both of these are always present
 		RDFTermFactory factory = getRdfTermFactory().get();
-		Graph graph = getIntoGraph().get();
+		Consumer<Quad> t = getTarget();
 				
 		// well - each parsing is unique. This should hopefully
 		// catch any accidental double parsing
 		IRI parsing = factory.createIRI("urn:uuid:" + UUID.randomUUID());
-		graph.add(parsing, factory.createIRI("http://example.com/greeting"), 
-				factory.createLiteral("Hello world"));
+		t.accept(factory.createQuad(null, parsing, factory.createIRI("http://example.com/greeting"), 
+				factory.createLiteral("Hello world")));
 		
 		// Now we'll expose the finalized AbstractRDFParserBuilder settings
 		// so they can be inspected by the junit test
 
 		if (getSourceIri().isPresent()) {
-			graph.add(parsing, 
+			t.accept(factory.createQuad(null, parsing, 
 					factory.createIRI("http://example.com/source"),
-					getSourceIri().get());			
+					getSourceIri().get()));			
 		}		
 		if (getSourceFile().isPresent()) {
-			graph.add(parsing, 
+			t.accept(factory.createQuad(null, parsing, 
 					factory.createIRI("http://example.com/source"),
-					factory.createIRI(getSourceFile().get().toUri().toString()));
+					factory.createIRI(getSourceFile().get().toUri().toString())));
 		}
 		if (getSourceInputStream().isPresent()) { 
-			graph.add(parsing, 
+			t.accept(factory.createQuad(null, parsing, 
 					factory.createIRI("http://example.com/source"),
-					factory.createBlankNode());
+					factory.createBlankNode()));
 		}
 
 		if (getBase().isPresent()) { 
-			graph.add(parsing, 
+			t.accept(factory.createQuad(null, parsing, 
 					factory.createIRI("http://example.com/base"),
-					getBase().get());
+					getBase().get()));
 		}
 		if (getContentType().isPresent()) {
-			graph.add(parsing, 
+			t.accept(factory.createQuad(null, parsing, 
 					factory.createIRI("http://example.com/contentType"),
-					factory.createLiteral(getContentType().get()));
+					factory.createLiteral(getContentType().get())));
 		}
 		if (getContentTypeSyntax().isPresent()) {
-			graph.add(parsing, 
+			t.accept(factory.createQuad(null, parsing, 
 					factory.createIRI("http://example.com/contentTypeSyntax"),
-					factory.createLiteral(getContentTypeSyntax().get().name()));
+					factory.createLiteral(getContentTypeSyntax().get().name())));
 		}		
 	}
 


[02/36] incubator-commonsrdf git commit: javadoc typos

Posted by st...@apache.org.
javadoc typos


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/4aacf85c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/4aacf85c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/4aacf85c

Branch: refs/heads/master
Commit: 4aacf85cb328f96fd619e98337980f65b894d6e4
Parents: 3667592
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Sun Mar 27 21:32:26 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Apr 1 16:19:58 2016 +0100

----------------------------------------------------------------------
 .../commons/rdf/api/RDFParserBuilder.java       | 21 ++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/4aacf85c/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index 0aacb6a..2cc60bb 100644
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -29,8 +29,8 @@ import java.util.concurrent.Future;
  * This interface follows the
  * <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder pattern</a>,
  * allowing to set parser settings like {@link #contentType(RDFSyntax)} and
- * {@link #base(IRI)}. A caller MUST at least call one of the
- * <code>source</code> methods before calling {@link #parse()} on the returned
+ * {@link #base(IRI)}. A caller MUST call one of the
+ * {@link #source(IRI)} methods before calling {@link #parse()} on the returned
  * RDFParserBuilder.
  * <p>
  * It is undefined if a RDFParserBuilder is mutable or thread-safe, so callers
@@ -98,8 +98,8 @@ public interface RDFParserBuilder {
 	 * any <code>Content-Type</code> headers or equivalent.
 	 * <p>
 	 * The content type MAY include a <code>charset</code> parameter if the RDF
-	 * media types which permit it; if <code>charset</code> is not specified the
-	 * default is {@link StandardCharsets#UTF_8} unless overridden within the
+	 * media types permit it; the default charset 
+	 * is {@link StandardCharsets#UTF_8} unless overridden within the
 	 * document.
 	 * <p>
 	 * This method will override any contentType set with
@@ -112,21 +112,22 @@ public interface RDFParserBuilder {
 	 *            <a href="https://tools.ietf.org/html/rfc7231#section-3.1.1.1">
 	 *            RFC7231</a>.
 	 * @throws IllegalArgumentException
-	 *             If this RDFParserBuilder does not support the specified
-	 *             content-type, or it has an invalid syntax.
+	 *             If the contentType has an invalid syntax, 
+	 *             or this RDFParserBuilder does not support the specified
+	 *             contentType.
 	 * @return An {@link RDFParserBuilder} that will use the specified content
 	 *         type.
 	 */
 	RDFParserBuilder contentType(String contentType);
 
 	/**
-	 * Specify which {@link Graph} to add triples into.
+	 * Specify which {@link Graph} to add triples to.
 	 * <p>
-	 * The default if this option has not been set is that each call to
-	 * {@link #parse()} will return a new {@link Graph} (created using
+	 * The default (if this option has not been set) is that each call to
+	 * {@link #parse()} return a new {@link Graph}, which is created using
 	 * {@link RDFTermFactory#createGraph()} 
 	 * if {@link #rdfTermFactory(RDFTermFactory)}
-	 * has been set).
+	 * has been set.
 	 * 
 	 * @param graph
 	 *            The {@link Graph} to add triples into.


[08/36] incubator-commonsrdf git commit: An abstract implementation of RDFParserBuilder

Posted by st...@apache.org.
An abstract implementation of RDFParserBuilder


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/8d548d50
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/8d548d50
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/8d548d50

Branch: refs/heads/master
Commit: 8d548d5005eef1ebf373bf666f31af039ad58c04
Parents: 6f1f669
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Fri Apr 1 17:05:34 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Apr 1 17:05:34 2016 +0100

----------------------------------------------------------------------
 .../rdf/simple/AbstractRDFParserBuilder.java    | 393 +++++++++++++++++++
 1 file changed, 393 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/8d548d50/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
new file mode 100644
index 0000000..925a365
--- /dev/null
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
@@ -0,0 +1,393 @@
+/**
+ * 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.commons.rdf.simple;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.text.ParseException;
+import java.util.Optional;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.apache.commons.rdf.api.Graph;
+import org.apache.commons.rdf.api.IRI;
+import org.apache.commons.rdf.api.RDFParserBuilder;
+import org.apache.commons.rdf.api.RDFSyntax;
+import org.apache.commons.rdf.api.RDFTermFactory;
+
+/**
+ * Abstract RDFParserBuilder
+ * <p>
+ * This abstract class keeps the builder properties in protected fields like
+ * {@link #sourceFile} using {@link Optional}. Some basic checking like
+ * {@link #checkIsAbsolute(IRI)} is performed.
+ * <p>
+ * This class and its subclasses are {@link Cloneable}, immutable and
+ * (therefore) thread-safe - each call to option methods like
+ * {@link #contentType(String)} or {@link #source(IRI)} will return a cloned,
+ * mutated copy.
+ * <p>
+ * By default, parsing is done by the abstract method
+ * {@link #parseSynchronusly()} - which is executed in a cloned snapshot - hence
+ * multiple {@link #parse()} calls are thread-safe. The default {@link #parse()}
+ * uses a thread pool in {@link #threadGroup} - but implementations can override
+ * {@link #parse()} (e.g. because it has its own threading model or use
+ * asynchronou  remote execution).
+ */
+public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Cloneable {
+
+	public static final ThreadGroup threadGroup = new ThreadGroup("Commons RDF parsers");
+	private static final ExecutorService threadpool = Executors.newCachedThreadPool(r -> new Thread(threadGroup, r));
+
+	// Basically only used for creating IRIs
+	private static RDFTermFactory internalRdfTermFactory = new SimpleRDFTermFactory();
+
+	/**
+	 * Get the set {@link RDFTermFactory}, if any.
+	 */
+	public Optional<RDFTermFactory> getRdfTermFactory() {
+		return rdfTermFactory;
+	}
+
+	/**
+	 * Get the set content-type {@link RDFSyntax}, if any.
+	 * <p>
+	 * If this is {@link Optional#isPresent()}, then 
+	 * {@link #getContentType()} contains the 
+	 * value of {@link RDFSyntax#mediaType}. 
+	 */
+	public Optional<RDFSyntax> getContentTypeSyntax() {
+		return contentTypeSyntax;
+	}
+	
+	/**
+	 * Get the set content-type String, if any.
+	 * <p>
+	 * If this is {@link Optional#isPresent()} and 
+	 * is recognized by {@link RDFSyntax#byMediaType(String)}, then
+	 * the corresponding {@link RDFSyntax} is set on 
+	 * {@link #getContentType()}, otherwise that is
+	 * {@link Optional#empty()}. 
+	 */
+	public final Optional<String> getContentType() {
+		return contentType;
+	}
+
+	/**
+	 * Get the set {@link Graph} to insert into, if any.
+	 * <p>
+	 * From the call to {@link #parseSynchronusly()}, this
+	 * method is always {@link Optional#isPresent()}
+	 * with a new {@link Graph} instance, and 
+	 * will be the value returned from {@link #parse()}.
+	 */	
+	public Optional<Graph> getIntoGraph() {
+		return intoGraph;
+	}
+
+	/**
+	 * Get the set base {@link IRI}, if present.
+	 * <p>
+	 * 
+	 */	
+	public Optional<IRI> getBase() {
+		return base;
+	}
+
+	/**
+	 * Get the set source {@link InputStream}.
+	 * <p>
+	 * If this is {@link Optional#isPresent()}, then 
+	 * {@link #getSourceFile()} and {@link #getSourceIri()}
+	 * are {@link Optional#empty()}.
+	 */
+	public Optional<InputStream> getSourceInputStream() {
+		return sourceInputStream;
+	}
+
+	/**
+	 * Get the set source {@link Path}.
+	 * <p>
+	 * If this is {@link Optional#isPresent()}, then 
+	 * {@link #getSourceInputStream()} and {@link #getSourceIri()}
+	 * are {@link Optional#empty()}.
+	 */	
+	public Optional<Path> getSourceFile() {
+		return sourceFile;
+	}
+
+	/**
+	 * Get the set source {@link Path}.
+	 * <p>
+	 * If this is {@link Optional#isPresent()}, then 
+	 * {@link #getSourceInputStream()} and {@link #getSourceInputStream()()}
+	 * are {@link Optional#empty()}.
+	 */		
+	public Optional<IRI> getSourceIri() {
+		return sourceIri;
+	}
+
+	private Optional<RDFTermFactory> rdfTermFactory = Optional.empty();
+	private Optional<RDFSyntax> contentTypeSyntax = Optional.empty();
+	private Optional<String> contentType = Optional.empty();
+	private Optional<Graph> intoGraph = Optional.empty();
+	private Optional<IRI> base = Optional.empty();
+	private Optional<InputStream> sourceInputStream = Optional.empty();
+	private Optional<Path> sourceFile = Optional.empty();
+	private Optional<IRI> sourceIri = Optional.empty();
+
+	@Override
+	public AbstractRDFParserBuilder clone() {
+		try {
+			return (AbstractRDFParserBuilder) super.clone();
+		} catch (CloneNotSupportedException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	@Override
+	public RDFParserBuilder rdfTermFactory(RDFTermFactory rdfTermFactory) {
+		AbstractRDFParserBuilder c = clone();
+		c.rdfTermFactory = Optional.ofNullable(rdfTermFactory);
+		return c;
+	}
+
+	@Override
+	public RDFParserBuilder contentType(RDFSyntax rdfSyntax) throws IllegalArgumentException {
+		AbstractRDFParserBuilder c = clone();
+		c.contentTypeSyntax = Optional.ofNullable(rdfSyntax);
+		c.contentType = c.contentTypeSyntax.map(syntax -> syntax.mediaType);
+		return c;
+	}
+
+	@Override
+	public RDFParserBuilder contentType(String contentType) {
+		AbstractRDFParserBuilder c = clone();
+		c.contentType = Optional.ofNullable(contentType);
+		c.contentTypeSyntax = c.contentType.flatMap(RDFSyntax::byMediaType);
+		return c;
+	}
+
+	@Override
+	public RDFParserBuilder intoGraph(Graph graph) {
+		AbstractRDFParserBuilder c = clone();
+		c.intoGraph = Optional.ofNullable(graph);
+		return c;
+	}
+
+	@Override
+	public RDFParserBuilder base(IRI base) {
+		AbstractRDFParserBuilder c = clone();
+		c.base = Optional.ofNullable(base);
+		c.base.ifPresent(i -> checkIsAbsolute(i));
+		return c;
+	}
+
+	@Override
+	public RDFParserBuilder base(String base) throws IllegalArgumentException {
+		return base(internalRdfTermFactory.createIRI(base));
+	}
+
+	@Override
+	public RDFParserBuilder source(InputStream inputStream) {
+		AbstractRDFParserBuilder c = clone();
+		c.resetSource();
+		c.sourceInputStream = Optional.ofNullable(inputStream);
+		return c;
+	}
+
+	@Override
+	public RDFParserBuilder source(Path file) {
+		AbstractRDFParserBuilder c = clone();
+		c.resetSource();
+		c.sourceFile = Optional.ofNullable(file);
+		return c;
+	}
+
+	@Override
+	public RDFParserBuilder source(IRI iri) {
+		AbstractRDFParserBuilder c = clone();
+		c.resetSource();
+		c.sourceIri = Optional.ofNullable(iri);
+		c.sourceIri.ifPresent(i -> checkIsAbsolute(i));
+		return c;
+	}
+
+	@Override
+	public RDFParserBuilder source(String iri) throws IllegalArgumentException {
+		AbstractRDFParserBuilder c = clone();
+		c.resetSource();
+		c.sourceIri = Optional.ofNullable(iri).map(internalRdfTermFactory::createIRI);
+		c.sourceIri.ifPresent(i -> checkIsAbsolute(i));
+		return source(internalRdfTermFactory.createIRI(iri));
+	}
+
+	/**
+	 * Check if an iri is absolute.
+	 * <p>
+	 * Used by {@link #source(String)} and {@link #base(String)}
+	 * 
+	 * @param iri
+	 */
+	protected void checkIsAbsolute(IRI iri) {
+		if (!URI.create(iri.getIRIString()).isAbsolute()) {
+			throw new IllegalArgumentException("IRI is not absolute: " + iri);
+		}
+	}
+
+	/**
+	 * Check that one and only one source is present and valid.
+	 * <p>
+	 * Used by {@link #parse()}.
+	 * 
+	 * @param iri
+	 * @throws IOException
+	 */
+	protected void checkSource() throws IOException {
+		if (!sourceFile.isPresent() && !sourceInputStream.isPresent() && !sourceIri.isPresent()) {
+			throw new IllegalStateException("No source has been set");
+		}
+		if (sourceIri.isPresent() && sourceInputStream.isPresent()) {
+			throw new IllegalStateException("Both sourceIri and sourceInputStream have been set");
+		}
+		if (sourceIri.isPresent() && sourceFile.isPresent()) {
+			throw new IllegalStateException("Both sourceIri and sourceFile have been set");
+		}
+		if (sourceInputStream.isPresent() && sourceFile.isPresent()) {
+			throw new IllegalStateException("Both sourceInputStream and sourceFile have been set");
+		}
+		if (sourceFile.isPresent() && !sourceFile.filter(Files::isReadable).isPresent()) {
+			throw new IOException("Can't read file: " + sourceFile);
+		}
+	}
+
+	/**
+	 * Check if base is required.
+	 * 
+	 * @throws IllegalStateException if base is required, but not set.
+	 */
+	protected void checkBaseRequired() {
+		if (!base.isPresent() && sourceInputStream.isPresent()
+				&& !contentTypeSyntax.filter(t -> t == RDFSyntax.NQUADS || t == RDFSyntax.NTRIPLES).isPresent()) {
+			throw new IllegalStateException("base iri required for inputstream source");
+		}
+	}
+
+	/**
+	 * Reset all source* fields to Optional.empty()
+	 * <p>
+	 * Subclasses should override this and call <code>super.resetSource()</code>
+	 * if they need to reset any additional source* fields.
+	 * 
+	 */
+	protected void resetSource() {
+		sourceInputStream = Optional.empty();
+		sourceIri = Optional.empty();
+		sourceFile = Optional.empty();
+	}
+
+	/**
+	 * Parse {@link #sourceInputStream}, {@link #sourceFile} or
+	 * {@link #sourceIri}.
+	 * <p>
+	 * One of the source fields MUST be present, as checked by {@link #checkSource()}.
+	 * <p>
+	 * {@link #checkBaseRequired()} is called to verify if {@link #getBase()} is required.
+	 * <p>
+	 * When this method is called, {@link #intoGraph} MUST always be present, as
+	 * that is where the parsed triples MUST be inserted into.
+	 * <p>
+	 * 
+	 * @return
+	 * @throws IOException
+	 * @throws IllegalStateException
+	 * @throws ParseException
+	 */
+	protected abstract void parseSynchronusly() throws IOException, IllegalStateException, ParseException;
+
+	/**
+	 * Prepare a clone of this RDFParserBuilder which have been checked and
+	 * completed.
+	 * <p>
+	 * The returned clone will always have
+	 * {@link #getIntoGraph()} and {@link #getRdfTermFactory()} present.
+	 * <p>
+	 * If the {@link #getSourceFile()} is present, but the 
+	 * {@link #getBase()} is not present, the base will be set to the
+	 * <code>file:///</code> IRI for the Path's real path (e.g. resolving any 
+	 * symbolic links).  
+	 *  
+	 * @return
+	 * @throws IOException
+	 * @throws IllegalStateException
+	 */
+	protected AbstractRDFParserBuilder prepareForParsing() throws IOException, IllegalStateException {
+		checkSource();
+		checkBaseRequired();
+		// We'll make a clone of our current state which will be passed to
+		// parseSynchronously()
+		AbstractRDFParserBuilder c = clone();
+
+		// Use a fresh SimpleRDFTermFactory for each parse
+		if (!c.rdfTermFactory.isPresent()) {
+			c.rdfTermFactory = Optional.of(createRDFTermFactory());
+		}
+		// No graph? We'll create one.
+		if (!c.intoGraph.isPresent()) {
+			c.intoGraph = c.rdfTermFactory.map(RDFTermFactory::createGraph);
+		}
+		// sourceFile, but no base? Let's follow any symlinks and use
+		// the file:/// URI
+		if (c.sourceFile.isPresent() && !c.base.isPresent()) {
+			URI baseUri = c.sourceFile.get().toRealPath().toUri();
+			c.base = Optional.of(internalRdfTermFactory.createIRI(baseUri.toString()));
+		}
+		return c;
+	}
+
+	/**
+	 * Create a new {@link RDFTermFactory} for a parse session.
+	 * <p>
+	 * This is called by {@link #parse()} to set 
+	 * {@link #rdfTermFactory(RDFTermFactory)} if it is
+	 * {@link Optional#empty()}, and therefore used also for 
+	 * creating a new {@link Graph} if 
+	 * {@link #getIntoGraph()} is {@link Optional#empty()}.
+	 * <p>
+	 * 
+	 * 
+	 * @return
+	 */
+	protected RDFTermFactory createRDFTermFactory() {
+		return new SimpleRDFTermFactory();
+	}
+
+	@Override
+	public Future<Graph> parse() throws IOException, IllegalStateException {
+		final AbstractRDFParserBuilder c = prepareForParsing();
+		return threadpool.submit(() -> {
+			c.parseSynchronusly();
+			return c.intoGraph.get();
+		});
+	}
+
+}


[14/36] incubator-commonsrdf git commit: more about builder pattern

Posted by st...@apache.org.
more about builder pattern


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/b4342b94
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/b4342b94
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/b4342b94

Branch: refs/heads/master
Commit: b4342b94fa6ff992986bf6141325f97d6d6a4583
Parents: c3fd214
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Sun Apr 3 02:54:28 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Sun Apr 3 02:54:28 2016 +0100

----------------------------------------------------------------------
 .../org/apache/commons/rdf/api/RDFParserBuilder.java    | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/b4342b94/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index 03dcc48..bc7d750 100644
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -29,8 +29,16 @@ import java.util.concurrent.Future;
  * This interface follows the
  * <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder pattern</a>,
  * allowing to set parser settings like {@link #contentType(RDFSyntax)} and
- * {@link #base(IRI)}. A caller MUST call one of the {@link #source(IRI)}
- * methods before calling {@link #parse()} on the returned RDFParserBuilder.
+ * {@link #base(IRI)}. A caller MUST call one of the <code>source</code> methods
+ * (e.g. {@link #source(IRI)}, {@link #source(Path)},
+ * {@link #source(InputStream)}) before calling {@link #parse()} on the returned
+ * RDFParserBuilder - however methods can be called in any order.
+ * <p>
+ * Setting a method that has already been set will override any existing value
+ * in the returned builder - irregardless of the parameter type (e.g.
+ * {@link #source(IRI)} will override a previous {@link #source(Path)}. Settings
+ * can be unset by passing <code>null</code> - this may require casting, e.g.
+ * <code>contentType( (RDFSyntax) null )</code>.
  * <p>
  * It is undefined if a RDFParserBuilder is mutable or thread-safe, so callers
  * should always use the returned modified RDFParserBuilder from the builder


[27/36] incubator-commonsrdf git commit: AbstractRDFParserBuilder generic

Posted by st...@apache.org.
AbstractRDFParserBuilder generic

so that the build methods can return the correct subtype
of itself


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/0a5be9db
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/0a5be9db
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/0a5be9db

Branch: refs/heads/master
Commit: 0a5be9dbb9634637e19aa3aaeb56e6865b702577
Parents: ddc545e
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Mon Jul 4 12:07:01 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Mon Jul 4 12:07:01 2016 +0100

----------------------------------------------------------------------
 .../rdf/simple/AbstractRDFParserBuilder.java    | 111 +++++++++----------
 .../commons/rdf/simple/RDFParseException.java   |  50 +++++++++
 .../rdf/simple/DummyRDFParserBuilder.java       |   2 +-
 3 files changed, 102 insertions(+), 61 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/0a5be9db/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
index cc5fad0..4a5b4d1 100644
--- a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
@@ -33,6 +33,7 @@ import org.apache.commons.rdf.api.Graph;
 import org.apache.commons.rdf.api.IRI;
 import org.apache.commons.rdf.api.Quad;
 import org.apache.commons.rdf.api.RDFParserBuilder;
+import org.apache.commons.rdf.api.RDFParserBuilder.ParseResult;
 import org.apache.commons.rdf.api.RDFSyntax;
 import org.apache.commons.rdf.api.RDFTermFactory;
 
@@ -53,28 +54,10 @@ import org.apache.commons.rdf.api.RDFTermFactory;
  * multiple {@link #parse()} calls are thread-safe. The default {@link #parse()}
  * uses a thread pool in {@link #threadGroup} - but implementations can override
  * {@link #parse()} (e.g. because it has its own threading model or use
- * asynchronou  remote execution).
+ * asynchronous remote execution).
  */
-public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Cloneable {
-
-	public class RDFParseException extends Exception {		
-		private static final long serialVersionUID = 5427752643780702976L;
-		public RDFParseException() {
-			super();
-		}
-		public RDFParseException(String message, Throwable cause) {
-			super(message, cause);
-		}
-		public RDFParseException(String message) {
-			super(message);
-		}
-		public RDFParseException(Throwable cause) {
-			super(cause);
-		}
-		public RDFParserBuilder getRDFParserBuilder() {
-			return AbstractRDFParserBuilder.this;
-		}
-	}
+public abstract class AbstractRDFParserBuilder<T extends AbstractRDFParserBuilder<T>> 
+	implements RDFParserBuilder, Cloneable {
 	
 	public static final ThreadGroup threadGroup = new ThreadGroup("Commons RDF parsers");
 	private static final ExecutorService threadpool = Executors.newCachedThreadPool(r -> new Thread(threadGroup, r));
@@ -212,79 +195,85 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	private Optional<Dataset> targetDataset;
 	private Optional<Graph> targetGraph;
 
+	@SuppressWarnings("unchecked")
 	@Override
-	public AbstractRDFParserBuilder clone() {
+	public T clone() {
 		try {
-			return (AbstractRDFParserBuilder) super.clone();
+			return (T) super.clone();
 		} catch (CloneNotSupportedException e) {
 			throw new RuntimeException(e);
 		}
 	}
 
+	@SuppressWarnings("unchecked")
+	protected T asT() { 
+		return (T) this;
+	}
+	
 	@Override
-	public RDFParserBuilder rdfTermFactory(RDFTermFactory rdfTermFactory) {
-		AbstractRDFParserBuilder c = clone();
+	public T rdfTermFactory(RDFTermFactory rdfTermFactory) {
+		AbstractRDFParserBuilder<T> c = clone();
 		c.rdfTermFactory = Optional.ofNullable(rdfTermFactory);
-		return c;
+		return c.asT();
 	}
 
 	@Override
-	public RDFParserBuilder contentType(RDFSyntax rdfSyntax) throws IllegalArgumentException {
-		AbstractRDFParserBuilder c = clone();
+	public T contentType(RDFSyntax rdfSyntax) throws IllegalArgumentException {
+		AbstractRDFParserBuilder<T> c = clone();
 		c.contentTypeSyntax = Optional.ofNullable(rdfSyntax);
 		c.contentType = c.contentTypeSyntax.map(syntax -> syntax.mediaType);
-		return c;
+		return c.asT();
 	}
 
 	@Override
-	public RDFParserBuilder contentType(String contentType) throws IllegalArgumentException {
-		AbstractRDFParserBuilder c = clone();
+	public T contentType(String contentType) throws IllegalArgumentException {
+		AbstractRDFParserBuilder<T> c = clone();
 		c.contentType = Optional.ofNullable(contentType);
 		c.contentTypeSyntax = c.contentType.flatMap(RDFSyntax::byMediaType);
-		return c;
+		return c.asT();
 	}
 
 	@Override
-	public RDFParserBuilder base(IRI base) {
-		AbstractRDFParserBuilder c = clone();
+	public T base(IRI base) {
+		AbstractRDFParserBuilder<T> c = clone();
 		c.base = Optional.ofNullable(base);
 		c.base.ifPresent(i -> checkIsAbsolute(i));
-		return c;
+		return c.asT();
 	}
 
 	@Override
-	public RDFParserBuilder base(String base) throws IllegalArgumentException {
+	public T base(String base) throws IllegalArgumentException {
 		return base(internalRdfTermFactory.createIRI(base));
 	}
 
 	@Override
-	public RDFParserBuilder source(InputStream inputStream) {
-		AbstractRDFParserBuilder c = clone();
+	public T source(InputStream inputStream) {
+		AbstractRDFParserBuilder<T> c = clone();
 		c.resetSource();
 		c.sourceInputStream = Optional.ofNullable(inputStream);
-		return c;
+		return c.asT();
 	}
 
 	@Override
-	public RDFParserBuilder source(Path file) {
-		AbstractRDFParserBuilder c = clone();
+	public T source(Path file) {
+		AbstractRDFParserBuilder<T> c = clone();
 		c.resetSource();
 		c.sourceFile = Optional.ofNullable(file);
-		return c;
+		return c.asT();
 	}
 
 	@Override
-	public RDFParserBuilder source(IRI iri) {
-		AbstractRDFParserBuilder c = clone();
+	public T source(IRI iri) {
+		AbstractRDFParserBuilder<T> c = clone();
 		c.resetSource();
 		c.sourceIri = Optional.ofNullable(iri);
 		c.sourceIri.ifPresent(i -> checkIsAbsolute(i));
-		return c;
+		return c.asT();
 	}
 
 	@Override
-	public RDFParserBuilder source(String iri) throws IllegalArgumentException {
-		AbstractRDFParserBuilder c = clone();
+	public T source(String iri) throws IllegalArgumentException {
+		AbstractRDFParserBuilder<T> c = clone();
 		c.resetSource();
 		c.sourceIri = Optional.ofNullable(iri).map(internalRdfTermFactory::createIRI);
 		c.sourceIri.ifPresent(i -> checkIsAbsolute(i));
@@ -407,7 +396,7 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	 * @throws IOException If the source was not accessible (e.g. a file was not found)
 	 * @throws IllegalStateException If the parser was not in a compatible setting (e.g. contentType was an invalid string) 
 	 */
-	protected AbstractRDFParserBuilder prepareForParsing() throws IOException, IllegalStateException {
+	protected T prepareForParsing() throws IOException, IllegalStateException {
 		checkSource();
 		checkBaseRequired();		
 		checkContentType();
@@ -415,7 +404,7 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 
 		// We'll make a clone of our current state which will be passed to
 		// parseSynchronously()
-		AbstractRDFParserBuilder c = clone();
+		AbstractRDFParserBuilder<T> c = clone();
 
 		// Use a fresh SimpleRDFTermFactory for each parse
 		if (!c.rdfTermFactory.isPresent()) {
@@ -428,7 +417,7 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 			c.base = Optional.of(internalRdfTermFactory.createIRI(baseUri.toString()));
 		}
 
-		return c;
+		return c.asT();
 	}
 	
 	/**
@@ -519,7 +508,7 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 
 	@Override
 	public Future<ParseResult> parse() throws IOException, IllegalStateException {
-		final AbstractRDFParserBuilder c = prepareForParsing();
+		final AbstractRDFParserBuilder<T> c = prepareForParsing();
 		return threadpool.submit(() -> {
 			c.parseSynchronusly();
 			return null;
@@ -527,27 +516,29 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	}
 
 	@Override
-	public RDFParserBuilder target(Consumer<Quad> consumer) {
-		AbstractRDFParserBuilder c = clone();
+	public T target(Consumer<Quad> consumer) {
+		AbstractRDFParserBuilder<T> c = clone();
 		c.resetTarget();
 		c.target = consumer;
-		return c;
+		return c.asT();
 	}
 	
 	@Override
-	public RDFParserBuilder target(Dataset dataset) {
-		AbstractRDFParserBuilder c = (AbstractRDFParserBuilder) RDFParserBuilder.super.target(dataset);
+	public T target(Dataset dataset) {
+		@SuppressWarnings({ "rawtypes", "unchecked" })
+		AbstractRDFParserBuilder<T> c = (AbstractRDFParserBuilder) RDFParserBuilder.super.target(dataset);
 		c.resetTarget();
 		c.targetDataset = Optional.of(dataset);
-		return c;
+		return c.asT();
 	}
 	
 	@Override
-	public RDFParserBuilder target(Graph graph) {
-		AbstractRDFParserBuilder c = (AbstractRDFParserBuilder) RDFParserBuilder.super.target(graph);
+	public T target(Graph graph) {
+		@SuppressWarnings({ "rawtypes", "unchecked" }) // super calls our .clone()
+		AbstractRDFParserBuilder<T> c = (AbstractRDFParserBuilder) RDFParserBuilder.super.target(graph);
 		c.resetTarget();
 		c.targetGraph = Optional.of(graph);
-		return c;
+		return c.asT();
 	}
 	
 

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/0a5be9db/simple/src/main/java/org/apache/commons/rdf/simple/RDFParseException.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/RDFParseException.java b/simple/src/main/java/org/apache/commons/rdf/simple/RDFParseException.java
new file mode 100644
index 0000000..ed16bb2
--- /dev/null
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/RDFParseException.java
@@ -0,0 +1,50 @@
+/**
+ * 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.commons.rdf.simple;
+
+import org.apache.commons.rdf.api.RDFParserBuilder;
+
+public class RDFParseException extends Exception {
+	private static final long serialVersionUID = 5427752643780702976L;
+	private RDFParserBuilder builder;
+
+	public RDFParseException(RDFParserBuilder builder) {
+		super();
+		this.builder = builder;
+	}
+
+	public RDFParseException(RDFParserBuilder builder, String message, Throwable cause) {
+		super(message, cause);
+		this.builder = builder;
+	}
+
+	public RDFParseException(RDFParserBuilder builder, String message) {
+		super(message);
+		this.builder = builder;
+	}
+
+	public RDFParseException(RDFParserBuilder builder, Throwable cause) {
+		super(cause);
+		this.builder = builder;
+	}
+
+	public RDFParserBuilder getRDFParserBuilder() {
+		return builder;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/0a5be9db/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java b/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
index 0cb7093..baf9768 100644
--- a/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
+++ b/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
@@ -43,7 +43,7 @@ import org.apache.commons.rdf.api.RDFTermFactory;
  * 
  *
  */
-public class DummyRDFParserBuilder extends AbstractRDFParserBuilder {
+public class DummyRDFParserBuilder extends AbstractRDFParserBuilder<DummyRDFParserBuilder> {
 	
 	@Override
 	protected void parseSynchronusly() throws IOException, IllegalStateException, RDFParseException {		


[24/36] incubator-commonsrdf git commit: target() in javadocs

Posted by st...@apache.org.
target() in javadocs


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/c0700de1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/c0700de1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/c0700de1

Branch: refs/heads/master
Commit: c0700de1f2adb83200f3443ef29e884a7ffae289
Parents: d153b4c
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Mon Jun 20 09:48:19 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Mon Jun 20 09:48:19 2016 +0100

----------------------------------------------------------------------
 .../org/apache/commons/rdf/api/RDFParserBuilder.java | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/c0700de1/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index 1425263..b387406 100644
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -22,6 +22,7 @@ import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
 import java.util.concurrent.Future;
+import java.util.function.Consumer;
 
 /**
  * Builder for parsing an RDF source into a Graph.
@@ -35,7 +36,7 @@ import java.util.concurrent.Future;
  * RDFParserBuilder - however methods can be called in any order.
  * <p>
  * The call to {@link #parse()} returns a {@link Future}, allowing asynchronous parse
- * operations. This can be combined with {@link #intoGraph(Graph)}
+ * operations. This can be combined with {@link #target(Graph)}
  * allowing access to the graph before parsing has completed,
  * however callers are still recommended to to check 
  * {@link Future#get()} for any exceptions thrown during parsing.
@@ -73,7 +74,7 @@ public interface RDFParserBuilder {
 	 * Specify which {@link RDFTermFactory} to use for generating
 	 * {@link RDFTerm}s.
 	 * <p>
-	 * This option may be used together with {@link #intoGraph(Graph)} to
+	 * This option may be used together with {@link #target(Graph)} to
 	 * override the implementation's default factory and graph.
 	 * <p>
 	 * <strong>Warning:</strong> Using the same {@link RDFTermFactory} for 
@@ -82,7 +83,7 @@ public interface RDFParserBuilder {
 	 * use the {@link RDFTermFactory#createBlankNode(String)} method
 	 * from the parsed blank node labels.
 	 * 
-	 * @see #intoGraph(Graph)
+	 * @see #target(Graph)
 	 * @param rdfTermFactory
 	 *            {@link RDFTermFactory} to use for generating RDFTerms.
 	 * @return An {@link RDFParserBuilder} that will use the specified
@@ -165,8 +166,12 @@ public interface RDFParserBuilder {
 	 * @return An {@link RDFParserBuilder} that will insert triples into the
 	 *         specified graph.
 	 */
-	RDFParserBuilder intoGraph(Graph graph);
+	default RDFParserBuilder target(Graph graph) {
+		return target(graph::add);
+	}
 
+	RDFParserBuilder target(Consumer<Triple> tripleConsumer);
+	
 	/**
 	 * Specify a base IRI to use for parsing any relative IRI references.
 	 * <p>
@@ -357,7 +362,7 @@ public interface RDFParserBuilder {
 	 * synchronous implementation MAY be blocking on the <code>parse()</code>
 	 * call and return a Future that is already {@link Future#isDone()}.
 	 * <p>
-	 * If {@link #intoGraph(Graph)} has been specified, this SHOULD be the same
+	 * If {@link #target(Graph)} has been specified, this SHOULD be the same
 	 * {@link Graph} instance returned from {@link Future#get()} once parsing has
 	 * completed successfully.
 	 * <p>


[32/36] incubator-commonsrdf git commit: target(Consumer) includes all triples

Posted by st...@apache.org.
target(Consumer<Quad>) includes all triples


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/72016682
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/72016682
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/72016682

Branch: refs/heads/master
Commit: 72016682262ca1e696bf8af78e27dc54f759544a
Parents: cbfb670
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Tue Sep 13 00:07:49 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Tue Sep 13 00:09:52 2016 +0100

----------------------------------------------------------------------
 .../commons/rdf/api/RDFParserBuilder.java       | 21 +++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/72016682/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index 0494502..dde92ac 100644
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -21,6 +21,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
+import java.util.Optional;
 import java.util.concurrent.Future;
 import java.util.function.Consumer;
 
@@ -43,7 +44,7 @@ import java.util.function.Consumer;
  * parsing.
  * <p>
  * Setting a method that has already been set will override any existing value
- * in the returned builder - irregardless of the parameter type (e.g.
+ * in the returned builder - regardless of the parameter type (e.g.
  * {@link #source(IRI)} will override a previous {@link #source(Path)}. Settings
  * can be unset by passing <code>null</code> - note that this may 
  * require casting, e.g. <code>contentType( (RDFSyntax) null )</code> 
@@ -220,6 +221,13 @@ public interface RDFParserBuilder {
 	/**
 	 * Specify a consumer for parsed quads.
 	 * <p>
+	 * The quads will include triples in all named graphs of the parsed 
+	 * source, including any triples in the default graph. 
+	 * When parsing a source format which do not support datasets, all quads 
+	 * delivered to the consumer will be in the default graph 
+	 * (e.g. their {@link Quad#getGraphName()} will be
+	 * as {@link Optional#empty()}), while for a source   
+	 * <p>
 	 * It is undefined if any quads are consumed if {@link #parse()} throws any
 	 * exceptions. On the other hand, if {@link #parse()} does not indicate an
 	 * exception, the implementation SHOULD have produced all parsed quads to
@@ -243,7 +251,6 @@ public interface RDFParserBuilder {
 	 *            A {@link Consumer} of {@link Quad}s
 	 * @return An {@link RDFParserBuilder} that will call the consumer for into
 	 *         the specified dataset.
-	 * @return
 	 */
 	RDFParserBuilder target(Consumer<Quad> consumer);
 	
@@ -355,7 +362,7 @@ public interface RDFParserBuilder {
 	 * <p>
 	 * The source set will not be read before the call to {@link #parse()}.
 	 * <p>
-	 * If this builder does not support the given IRI (e.g.
+	 * If this builder does not support the given IRI protocol (e.g.
 	 * <code>urn:uuid:ce667463-c5ab-4c23-9b64-701d055c4890</code>), this method
 	 * should succeed, while the {@link #parse()} should throw an
 	 * {@link IOException}.
@@ -425,9 +432,9 @@ public interface RDFParserBuilder {
 	 * method) MUST have been called before calling this method, otherwise an
 	 * {@link IllegalStateException} will be thrown.
 	 * <p>
-	 * A target method (e.g. {@link #target(Consumer)}, {@link #target(Dataset)}
-	 * , {@link #target(Graph)} or an equivalent subclass method) MUST have been
-	 * called before calling this method, otherwise an
+	 * A target method (e.g. {@link #target(Consumer)}, {@link #target(Dataset)},
+	 * {@link #target(Graph)} or an equivalent subclass method) MUST have been
+	 * called before calling parse(), otherwise an
 	 * {@link IllegalStateException} will be thrown.
 	 * <p>
 	 * It is undefined if this method is thread-safe, however the
@@ -449,7 +456,7 @@ public interface RDFParserBuilder {
 	 * parsing succeeded.
 	 * <p>
 	 * If an exception occurs during parsing, (e.g. {@link IOException} or
-	 * {@link org.apache.commons.rdf.simple.AbstractRDFParserBuilder.RDFParseException}), 
+	 * {@link org.apache.commons.rdf.simple.RDFParseException}), 
 	 * it should be indicated as the
 	 * {@link java.util.concurrent.ExecutionException#getCause()} in the
 	 * {@link java.util.concurrent.ExecutionException} thrown on


[10/36] incubator-commonsrdf git commit: Add guessRDFSyntax() convenience method

Posted by st...@apache.org.
Add guessRDFSyntax() convenience method


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/478b20e2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/478b20e2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/478b20e2

Branch: refs/heads/master
Commit: 478b20e27b2e24494d20d6edbf7a80c3604a7879
Parents: 8dfc3f4
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Sun Apr 3 00:53:48 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Sun Apr 3 01:07:39 2016 +0100

----------------------------------------------------------------------
 .../rdf/simple/AbstractRDFParserBuilder.java    | 41 ++++++++++++++++++++
 1 file changed, 41 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/478b20e2/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
index 925a365..b31251d 100644
--- a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
@@ -361,10 +361,51 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 			URI baseUri = c.sourceFile.get().toRealPath().toUri();
 			c.base = Optional.of(internalRdfTermFactory.createIRI(baseUri.toString()));
 		}
+
 		return c;
 	}
 
 	/**
+	 * Guess RDFSyntax from a local file's extension.
+	 * <p>
+	 * This method can be used by subclasses if {@link #getContentType()} is not
+	 * present and {@link #getSourceFile()} is set.
+	 * 
+	 * @param path Path which extension should be checked
+	 * @return The {@link RDFSyntax} which has a matching {@link RDFSyntax#fileExtension}, 
+	 * 	otherwise {@link Optional#empty()}. 
+	 */
+	protected static Optional<RDFSyntax> guessRDFSyntax(Path path) {
+			return fileExtension(path).flatMap(RDFSyntax::byFileExtension);
+	}
+
+	/**
+	 * Return the file extension of a Path - if any.
+	 * <p>
+	 * The returned file extension includes the leading <code>.</code>
+	 * <p>
+	 * Note that this only returns the last extension, e.g. the 
+	 * file extension for <code>archive.tar.gz</code> would be <code>.gz</code>
+	 * 
+	 * @param path Path which filename might contain an extension
+	 * @return File extension (including the leading <code>.</code>, 
+	 * 	or {@link Optional#empty()} if the path has no extension
+	 */
+	private static Optional<String> fileExtension(Path path) {
+		Path fileName = path.getFileName();
+		if (fileName == null) { 
+			return Optional.empty();
+		}
+		String filenameStr = fileName.toString();
+		int last = filenameStr.lastIndexOf(".");
+		if (last > -1) { 
+			return Optional.of(filenameStr.substring(last));				
+		}
+		return Optional.empty();
+	}
+	
+
+	/**
 	 * Create a new {@link RDFTermFactory} for a parse session.
 	 * <p>
 	 * This is called by {@link #parse()} to set 


[15/36] incubator-commonsrdf git commit: DFParserBuilder javadoc on error conditions

Posted by st...@apache.org.
DFParserBuilder javadoc on error conditions


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/df35ebca
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/df35ebca
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/df35ebca

Branch: refs/heads/master
Commit: df35ebca2329019ae9468176eb6467b7ce0ba9bf
Parents: b4342b9
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Sun Apr 3 03:11:28 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Sun Apr 3 03:11:28 2016 +0100

----------------------------------------------------------------------
 .../commons/rdf/api/RDFParserBuilder.java       | 27 +++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/df35ebca/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index bc7d750..ee566c7 100644
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -34,22 +34,34 @@ import java.util.concurrent.Future;
  * {@link #source(InputStream)}) before calling {@link #parse()} on the returned
  * RDFParserBuilder - however methods can be called in any order.
  * <p>
+ * The call to {@link #parse()} returns a {@link Future}, allowing asynchronous parse
+ * operations. This can be combined with {@link #intoGraph(Graph)}
+ * allowing access to the graph before parsing has completed,
+ * however callers are still recommended to to check 
+ * {@link Future#get()} for any exceptions thrown during parsing.
+ * <p>
  * Setting a method that has already been set will override any existing value
  * in the returned builder - irregardless of the parameter type (e.g.
  * {@link #source(IRI)} will override a previous {@link #source(Path)}. Settings
  * can be unset by passing <code>null</code> - this may require casting, e.g.
- * <code>contentType( (RDFSyntax) null )</code>.
+ * <code>contentType( (RDFSyntax) null )</code> to undo a previous call to
+ * {@link #contentType(RDFSyntax)}.
  * <p>
  * It is undefined if a RDFParserBuilder is mutable or thread-safe, so callers
  * should always use the returned modified RDFParserBuilder from the builder
  * methods. The builder may return itself, or a cloned builder with the modified
- * settings applied.
+ * settings applied. Implementations are however encouraged to be 
+ * immutable and thread-safe and document this, 
+ * as an example starting point, see 
+ * {@link org.apache.commons.rdf.simple.AbstractRDFParserBuilder}.
  * <p>
  * Example usage:
  * </p>
  * 
  * <pre>
- *   Graph g1 = ExampleRDFParserBuilder.source("http://example.com/graph.rdf").parse();
+ *   // Retrieve populated graph from the Future
+ *   Graph g1 = ExampleRDFParserBuilder.source("http://example.com/graph.rdf").parse().get(30, TimeUnit.Seconds);
+ *   // Or parsing into an existing Graph:
  *   ExampleRDFParserBuilder.source(Paths.get("/tmp/graph.ttl").contentType(RDFSyntax.TURTLE).intoGraph(g1).parse();
  * </pre>
  * 
@@ -138,6 +150,15 @@ public interface RDFParserBuilder {
 	 * {@link #parse()} return a new {@link Graph}, which is created using
 	 * {@link RDFTermFactory#createGraph()} if
 	 * {@link #rdfTermFactory(RDFTermFactory)} has been set.
+	 * <p>
+	 * It is undefined if any triples are added to the specified
+	 * {@link Graph} if the {@link Future#get()} returned from 
+	 * {@link #parse()} throws any exceptions. (However 
+	 * implementations are free to prevent this using transaction 
+	 * mechanisms or similar).  However, if {@link Future#get()}
+	 * does not indicatean exception, the 
+	 * parser implementation SHOULD have inserted all parsed triples 
+	 * to the specified graph.
 	 * 
 	 * @param graph
 	 *            The {@link Graph} to add triples into.


[13/36] incubator-commonsrdf git commit: javadoc typos

Posted by st...@apache.org.
javadoc typos


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/c3fd214a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/c3fd214a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/c3fd214a

Branch: refs/heads/master
Commit: c3fd214abd8c291635deb4ba9bf7881c166931a0
Parents: b1597ff
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Sun Apr 3 02:47:34 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Sun Apr 3 02:47:34 2016 +0100

----------------------------------------------------------------------
 .../rdf/simple/AbstractRDFParserBuilder.java    | 21 ++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/c3fd214a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
index b31251d..34aeb5a 100644
--- a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
@@ -317,12 +317,10 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	 * that is where the parsed triples MUST be inserted into.
 	 * <p>
 	 * 
-	 * @return
-	 * @throws IOException
-	 * @throws IllegalStateException
-	 * @throws ParseException
+	 * @throws IOException If the source could not be read 
+	 * @throws ParseException If the source could not be parsed (e.g. a .ttl file was not valid Turtle)
 	 */
-	protected abstract void parseSynchronusly() throws IOException, IllegalStateException, ParseException;
+	protected abstract void parseSynchronusly() throws IOException, ParseException;
 
 	/**
 	 * Prepare a clone of this RDFParserBuilder which have been checked and
@@ -336,9 +334,9 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	 * <code>file:///</code> IRI for the Path's real path (e.g. resolving any 
 	 * symbolic links).  
 	 *  
-	 * @return
-	 * @throws IOException
-	 * @throws IllegalStateException
+	 * @return A completed and checked clone of this RDFParserBuilder
+	 * @throws IOException If the source was not accessible (e.g. a file was not found)
+	 * @throws IllegalStateException If the parser was not in a compatible setting (e.g. contentType was an invalid string) 
 	 */
 	protected AbstractRDFParserBuilder prepareForParsing() throws IOException, IllegalStateException {
 		checkSource();
@@ -414,9 +412,12 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	 * creating a new {@link Graph} if 
 	 * {@link #getIntoGraph()} is {@link Optional#empty()}.
 	 * <p>
+	 * As parsed blank nodes might be made with 
+	 * {@link RDFTermFactory#createBlankNode(String)}, 
+	 * each call to this method should return 
+	 * a new RDFTermFactory instance.
 	 * 
-	 * 
-	 * @return
+	 * @return A new {@link RDFTermFactory}
 	 */
 	protected RDFTermFactory createRDFTermFactory() {
 		return new SimpleRDFTermFactory();


[22/36] incubator-commonsrdf git commit: Merge branch 'quad' into parser-with-quads

Posted by st...@apache.org.
Merge branch 'quad' into parser-with-quads


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/036029bb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/036029bb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/036029bb

Branch: refs/heads/master
Commit: 036029bb50676fa65f873421b4cec556b14867fb
Parents: defdbd9 580484c
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Fri Jun 17 21:17:10 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Jun 17 21:17:10 2016 +0100

----------------------------------------------------------------------
 RELEASE-NOTES.txt                               |  39 ++++
 RELEASE-PROCESS.md                              |  16 ++
 api/pom.xml                                     |   2 +-
 .../org/apache/commons/rdf/api/Dataset.java     |  12 +-
 .../java/org/apache/commons/rdf/api/Graph.java  |  40 +++-
 .../org/apache/commons/rdf/api/GraphLike.java   |  98 ++++++++++
 .../java/org/apache/commons/rdf/api/Quad.java   |   7 +-
 .../org/apache/commons/rdf/api/QuadLike.java    |  57 ++++++
 .../java/org/apache/commons/rdf/api/Triple.java |   2 +-
 .../org/apache/commons/rdf/api/TripleLike.java  |  61 ++++++
 .../apache/commons/rdf/api/TripleOrQuad.java    |  64 -------
 .../commons/rdf/api/AbstractGraphTest.java      | 192 ++++++++++++++++++-
 .../rdf/api/AbstractRDFTermFactoryTest.java     |  29 +++
 examples/pom.xml                                |   4 +-
 examples/src/example/UserGuideTest.java         |   1 +
 pom.xml                                         |  95 ++++-----
 simple/pom.xml                                  |   3 +-
 .../commons/rdf/simple/DatasetGraphView.java    | 138 +++++++++++++
 .../apache/commons/rdf/simple/DatasetImpl.java  |  23 +--
 .../apache/commons/rdf/simple/GraphImpl.java    |  12 +-
 .../commons/rdf/simple/TestWritingGraph.java    |   8 +-
 src/assembly/src.xml                            |  45 +++++
 src/main/assembly/src.xml                       |  44 -----
 src/site/markdown/download.md                   |  34 ++--
 src/site/markdown/userguide.md                  |  60 ++++--
 25 files changed, 840 insertions(+), 246 deletions(-)
----------------------------------------------------------------------



[19/36] incubator-commonsrdf git commit: RDFParseException instead of ParseException

Posted by st...@apache.org.
RDFParseException instead of ParseException

as ParseException requires location, and don't
support getCause()


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/d153b4cb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/d153b4cb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/d153b4cb

Branch: refs/heads/master
Commit: d153b4cb6837ba52b3a119bb3846bfc02bfb8ae9
Parents: 1b5f316
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Tue Apr 12 09:11:26 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Tue Apr 12 09:11:26 2016 +0100

----------------------------------------------------------------------
 .../rdf/simple/AbstractRDFParserBuilder.java    | 24 +++++++++++++++++---
 .../rdf/simple/DummyRDFParserBuilder.java       |  2 +-
 2 files changed, 22 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/d153b4cb/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
index 98790ca..ab37eef 100644
--- a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
@@ -22,7 +22,6 @@ import java.io.InputStream;
 import java.net.URI;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.text.ParseException;
 import java.util.Optional;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -55,6 +54,25 @@ import org.apache.commons.rdf.api.RDFTermFactory;
  */
 public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Cloneable {
 
+	public class RDFParseException extends Exception {		
+		private static final long serialVersionUID = 5427752643780702976L;
+		public RDFParseException() {
+			super();
+		}
+		public RDFParseException(String message, Throwable cause) {
+			super(message, cause);
+		}
+		public RDFParseException(String message) {
+			super(message);
+		}
+		public RDFParseException(Throwable cause) {
+			super(cause);
+		}
+		public RDFParserBuilder getRDFParserBuilder() {
+			return AbstractRDFParserBuilder.this;
+		}
+	}
+	
 	public static final ThreadGroup threadGroup = new ThreadGroup("Commons RDF parsers");
 	private static final ExecutorService threadpool = Executors.newCachedThreadPool(r -> new Thread(threadGroup, r));
 
@@ -321,9 +339,9 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	 * <p>
 	 * 
 	 * @throws IOException If the source could not be read 
-	 * @throws ParseException If the source could not be parsed (e.g. a .ttl file was not valid Turtle)
+	 * @throws RDFParseException If the source could not be parsed (e.g. a .ttl file was not valid Turtle)
 	 */
-	protected abstract void parseSynchronusly() throws IOException, ParseException;
+	protected abstract void parseSynchronusly() throws IOException, RDFParseException;
 
 	/**
 	 * Prepare a clone of this RDFParserBuilder which have been checked and

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/d153b4cb/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java b/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
index ddaf4ed..cc62f0c 100644
--- a/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
+++ b/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
@@ -46,7 +46,7 @@ import org.apache.commons.rdf.api.RDFTermFactory;
 public class DummyRDFParserBuilder extends AbstractRDFParserBuilder {
 	
 	@Override
-	protected void parseSynchronusly() throws IOException, IllegalStateException, ParseException {		
+	protected void parseSynchronusly() throws IOException, IllegalStateException, RDFParseException {		
 		// From parseSynchronusly both of these are always present
 		RDFTermFactory factory = getRdfTermFactory().get();
 		Graph graph = getIntoGraph().get();


[12/36] incubator-commonsrdf git commit: BlankNode RDFTermFactory warning

Posted by st...@apache.org.
BlankNode RDFTermFactory warning


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/b1597ff7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/b1597ff7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/b1597ff7

Branch: refs/heads/master
Commit: b1597ff7bac433f23a78b0eacbf5a5b5e7ffb089
Parents: 528af99
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Sun Apr 3 02:47:31 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Sun Apr 3 02:47:31 2016 +0100

----------------------------------------------------------------------
 .../apache/commons/rdf/api/RDFParserBuilder.java  | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/b1597ff7/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index 6d2d1d0..03dcc48 100644
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -55,6 +55,12 @@ public interface RDFParserBuilder {
 	 * <p>
 	 * This option may be used together with {@link #intoGraph(Graph)} to
 	 * override the implementation's default factory and graph.
+	 * <p>
+	 * <strong>Warning:</strong> Using the same {@link RDFTermFactory} for 
+	 * multiple {@link #parse()} calls  may accidentally merge 
+	 * {@link BlankNode}s having the same label, as the parser may 
+	 * use the {@link RDFTermFactory#createBlankNode(String)} method
+	 * from the parsed blank node labels.
 	 * 
 	 * @see #intoGraph(Graph)
 	 * @param rdfTermFactory
@@ -323,13 +329,13 @@ public interface RDFParserBuilder {
 	 * call and return a Future that is already {@link Future#isDone()}.
 	 * <p>
 	 * If {@link #intoGraph(Graph)} has been specified, this SHOULD be the same
-	 * {@link Graph} instance returned from {@link Future#get() once parsing has
+	 * {@link Graph} instance returned from {@link Future#get()} once parsing has
 	 * completed successfully.
 	 * <p>
 	 * If an exception occurs during parsing, (e.g. {@link IOException} or
-	 * {@link java.text.ParseException}, it should be indicated as the
-	 * {@link java.util.concurrent.ExecutionException#getCause()) in the
-	 * {@link java.util.concurrent.ExecutionException) thrown on
+	 * {@link java.text.ParseException}), it should be indicated as the
+	 * {@link java.util.concurrent.ExecutionException#getCause()} in the
+	 * {@link java.util.concurrent.ExecutionException} thrown on
 	 * {@link Future#get()}.
 	 * 
 	 * @return A Future that will return the populated {@link Graph} when the
@@ -338,8 +344,8 @@ public interface RDFParserBuilder {
 	 *             If an error occurred while starting to read the source (e.g.
 	 *             file not found, unsupported IRI protocol). Note that IO
 	 *             errors during parsing would instead be the
-	 *             {@link java.util.concurrent.ExecutionException#getCause()) of
-	 *             the {@link java.util.concurrent.ExecutionException) thrown on
+	 *             {@link java.util.concurrent.ExecutionException#getCause()} of
+	 *             the {@link java.util.concurrent.ExecutionException} thrown on
 	 *             {@link Future#get()}.
 	 * @throws IllegalStateException
 	 *             If the builder is in an invalid state, e.g. a


[18/36] incubator-commonsrdf git commit: contentType(String) also throws IllegalArgumentException

Posted by st...@apache.org.
contentType(String) also throws IllegalArgumentException

Added checkContentType() for subclasses


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/1b5f3160
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/1b5f3160
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/1b5f3160

Branch: refs/heads/master
Commit: 1b5f3160f590867d48247bba953cf39ca663456b
Parents: dc7589f
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Fri Apr 8 12:00:45 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Apr 8 12:00:45 2016 +0100

----------------------------------------------------------------------
 .../org/apache/commons/rdf/api/RDFParserBuilder.java  |  2 +-
 .../commons/rdf/simple/AbstractRDFParserBuilder.java  | 14 +++++++++++++-
 2 files changed, 14 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/1b5f3160/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index ee566c7..1425263 100644
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -141,7 +141,7 @@ public interface RDFParserBuilder {
 	 *             If the contentType has an invalid syntax, or this
 	 *             RDFParserBuilder does not support the specified contentType.
 	 */
-	RDFParserBuilder contentType(String contentType);
+	RDFParserBuilder contentType(String contentType) throws IllegalArgumentException;
 
 	/**
 	 * Specify which {@link Graph} to add triples to.

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/1b5f3160/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
index 2430d26..98790ca 100644
--- a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
@@ -180,7 +180,7 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	}
 
 	@Override
-	public RDFParserBuilder contentType(String contentType) {
+	public RDFParserBuilder contentType(String contentType) throws IllegalArgumentException {
 		AbstractRDFParserBuilder c = clone();
 		c.contentType = Optional.ofNullable(contentType);
 		c.contentTypeSyntax = c.contentType.flatMap(RDFSyntax::byMediaType);
@@ -344,6 +344,7 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	protected AbstractRDFParserBuilder prepareForParsing() throws IOException, IllegalStateException {
 		checkSource();
 		checkBaseRequired();
+		checkContentType();
 		// We'll make a clone of our current state which will be passed to
 		// parseSynchronously()
 		AbstractRDFParserBuilder c = clone();
@@ -365,6 +366,17 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 
 		return c;
 	}
+	
+	/**
+	 * Subclasses can override this method to check compatibility with the
+	 * contentType setting.
+	 * 
+	 * @throws IllegalStateException
+	 *             if the {@link #getContentType()} or
+	 *             {@link #getContentTypeSyntax()} is not compatible or invalid
+	 */
+	protected void checkContentType() throws IllegalStateException {
+	}
 
 	/**
 	 * Guess RDFSyntax from a local file's extension.


[25/36] incubator-commonsrdf git commit: Merge branch 'parser-writer-interface' into parser-with-quads

Posted by st...@apache.org.
Merge branch 'parser-writer-interface' into parser-with-quads


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/953e9b89
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/953e9b89
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/953e9b89

Branch: refs/heads/master
Commit: 953e9b8915fd7d42f8beac6fac8cabc39d5351e1
Parents: 7c69d4f c0700de
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Mon Jun 20 09:52:59 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Mon Jun 20 09:52:59 2016 +0100

----------------------------------------------------------------------
 api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/953e9b89/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --cc api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index 0494502,b387406..5e8ee33
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@@ -183,71 -166,13 +183,73 @@@ public interface RDFParserBuilder 
  	 * @return An {@link RDFParserBuilder} that will insert triples into the
  	 *         specified graph.
  	 */
 -	default RDFParserBuilder target(Graph graph) {
 -		return target(graph::add);
 +	default RDFParserBuilder target(Graph graph) {		
 +		return target(q -> { 
 +			if (! q.getGraphName().isPresent()) { 
 +				graph.add(q.asTriple());
 +			}
 +		});
  	}
  
+ 	RDFParserBuilder target(Consumer<Triple> tripleConsumer);
+ 	
  	/**
 +	 * Specify a {@link Dataset} to add parsed quads to.
 +	 * <p>
 +	 * It is undefined if any quads are added to the specified
 +	 * {@link Dataset} if {@link #parse()} throws any exceptions. 
 +	 * (However implementations are free to prevent this using transaction 
 +	 * mechanisms or similar).  On the other hand, if {@link #parse()}
 +	 * does not indicate an exception, the 
 +	 * implementation SHOULD have inserted all parsed quads 
 +	 * to the specified dataset.
 +	 * <p>
 +	 * Calling this method will override any earlier targets set with 
 +	 * {@link #target(Graph)}, {@link #target(Consumer)} or {@link #target(Dataset)}.
 +	 * <p>
 +	 * The default implementation of this method calls {@link #target(Consumer)}
 +	 * with a {@link Consumer} that does {@link Dataset#add(Quad)}.
 +	 * 
 +	 * @param dataset
 +	 *            The {@link Dataset} to add quads to.
 +	 * @return An {@link RDFParserBuilder} that will insert triples into the
 +	 *         specified dataset.
 +	 */
 +	default RDFParserBuilder target(Dataset dataset) {
 +		return target(dataset::add);
 +	}
 +
 +	/**
 +	 * Specify a consumer for parsed quads.
 +	 * <p>
 +	 * It is undefined if any quads are consumed if {@link #parse()} throws any
 +	 * exceptions. On the other hand, if {@link #parse()} does not indicate an
 +	 * exception, the implementation SHOULD have produced all parsed quads to
 +	 * the specified consumer.
 +	 * <p>
 +	 * Calling this method will override any earlier targets set with
 +	 * {@link #target(Graph)}, {@link #target(Consumer)} or
 +	 * {@link #target(Dataset)}.
 +	 * <p>
 +	 * The consumer is not assumed to be thread safe - only one
 +	 * {@link Consumer#accept(Object)} is delivered at a time for a given
 +	 * {@link RDFParserBuilder#parse()} call.
 +	 * <p>
 +	 * This method is typically called with a functional consumer, for example:
 +	 * <pre>
 +	 * List<Quad> quads = new ArrayList<Quad>;
 +	 * parserBuilder.target(quads::add).parse();
 +	 * </pre>
 +	 * 
 +	 * @param consumer
 +	 *            A {@link Consumer} of {@link Quad}s
 +	 * @return An {@link RDFParserBuilder} that will call the consumer for into
 +	 *         the specified dataset.
 +	 * @return
 +	 */
 +	RDFParserBuilder target(Consumer<Quad> consumer);
 +	
 +	/**
  	 * Specify a base IRI to use for parsing any relative IRI references.
  	 * <p>
  	 * Setting this option will override any protocol-specific base IRI (e.g.


[28/36] incubator-commonsrdf git commit: Merge branch 'quad' into parser-with-quads

Posted by st...@apache.org.
Merge branch 'quad' into parser-with-quads


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/c84a9ea2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/c84a9ea2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/c84a9ea2

Branch: refs/heads/master
Commit: c84a9ea2481719cee0c120879263b837eb1a1c12
Parents: 0a5be9d a1d6554
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Thu Jul 7 11:28:09 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Thu Jul 7 11:28:09 2016 +0100

----------------------------------------------------------------------
 .../org/apache/commons/rdf/api/GraphLike.java   | 21 +++++++++++++++---
 .../java/org/apache/commons/rdf/api/Quad.java   | 23 +++++++++++---------
 .../org/apache/commons/rdf/api/QuadLike.java    | 18 +++++++++++----
 .../apache/commons/rdf/api/RDFTermFactory.java  |  2 +-
 .../org/apache/commons/rdf/api/TripleLike.java  | 14 +++++++++---
 .../commons/rdf/simple/DatasetGraphView.java    |  2 +-
 6 files changed, 58 insertions(+), 22 deletions(-)
----------------------------------------------------------------------



[36/36] incubator-commonsrdf git commit: COMMONSRDF-39: Add RDFParser interface

Posted by st...@apache.org.
COMMONSRDF-39: Add RDFParser interface

Merge branch 'parser-with-quads'

See also #21


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/e0d31918
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/e0d31918
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/e0d31918

Branch: refs/heads/master
Commit: e0d319181ed8df721de6ee11f072622fb90e1c8a
Parents: de7fe8a 10d27cd
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Wed Sep 28 14:22:43 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Wed Sep 28 14:22:43 2016 +0100

----------------------------------------------------------------------
 .../commons/rdf/experimental/RDFParser.java     | 495 +++++++++++++++++
 .../commons/rdf/experimental/package-info.java  |  34 ++
 .../test/resources/example-rdf/example.jsonld   |  25 +
 api/src/test/resources/example-rdf/example.nq   |   3 +
 api/src/test/resources/example-rdf/example.nt   |   2 +
 api/src/test/resources/example-rdf/example.rdf  |  23 +
 api/src/test/resources/example-rdf/example.trig |   3 +
 api/src/test/resources/example-rdf/example.ttl  |   2 +
 .../simple/experimental/AbstractRDFParser.java  | 542 +++++++++++++++++++
 .../simple/experimental/RDFParseException.java  |  50 ++
 .../rdf/simple/experimental/package-info.java   |  34 ++
 .../rdf/simple/DummyRDFParserBuilder.java       |  98 ++++
 .../experimental/AbstractRDFParserTest.java     | 256 +++++++++
 13 files changed, 1567 insertions(+)
----------------------------------------------------------------------



[23/36] incubator-commonsrdf git commit: added getTargetDataset()/getTargetGraph()

Posted by st...@apache.org.
added getTargetDataset()/getTargetGraph()


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/7c69d4fd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/7c69d4fd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/7c69d4fd

Branch: refs/heads/master
Commit: 7c69d4fdc1511fe9cbad1cf4abc00d661d2a7871
Parents: 036029b
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Fri Jun 17 21:18:47 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Jun 17 21:18:47 2016 +0100

----------------------------------------------------------------------
 .../rdf/simple/AbstractRDFParserBuilder.java    | 78 ++++++++++++++++++++
 1 file changed, 78 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/7c69d4fd/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
index 9544928..cc5fad0 100644
--- a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
@@ -28,6 +28,8 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.function.Consumer;
 
+import org.apache.commons.rdf.api.Dataset;
+import org.apache.commons.rdf.api.Graph;
 import org.apache.commons.rdf.api.IRI;
 import org.apache.commons.rdf.api.Quad;
 import org.apache.commons.rdf.api.RDFParserBuilder;
@@ -123,6 +125,40 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	}
 
 	/**
+	 * Get the target dataset as set by {@link #target(Dataset)}.
+	 * <p>
+	 * The return value is {@link Optional#isPresent()} if and only if
+	 * {@link #target(Dataset)} has been set, meaning that the implementation
+	 * may choose to append parsed quads to the {@link Dataset} directly instead
+	 * of relying on the generated {@link #getTarget()} consumer.
+	 * <p>
+	 * If this value is present, then {@link #getTargetGraph()} MUST 
+	 * be {@link Optional#empty()}.
+	 * 
+	 * @return The target Dataset, or {@link Optional#empty()} if another kind of target has been set.
+	 */
+	public Optional<Dataset> getTargetDataset() {
+		return targetDataset;
+	}
+
+	/**
+	 * Get the target graph as set by {@link #target(Graph)}.
+	 * <p>
+	 * The return value is {@link Optional#isPresent()} if and only if
+	 * {@link #target(Graph)} has been set, meaning that the implementation
+	 * may choose to append parsed triples to the {@link Graph} directly instead
+	 * of relying on the generated {@link #getTarget()} consumer.
+	 * <p>
+	 * If this value is present, then {@link #getTargetDataset()} MUST 
+	 * be {@link Optional#empty()}.
+	 * 
+	 * @return The target Graph, or {@link Optional#empty()} if another kind of target has been set.
+	 */	
+	public Optional<Graph>  getTargetGraph() {
+		return targetGraph;
+	}
+	
+	/**
 	 * Get the set base {@link IRI}, if present.
 	 * <p>
 	 * 
@@ -164,6 +200,7 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 		return sourceIri;
 	}
 
+
 	private Optional<RDFTermFactory> rdfTermFactory = Optional.empty();
 	private Optional<RDFSyntax> contentTypeSyntax = Optional.empty();
 	private Optional<String> contentType = Optional.empty();
@@ -172,6 +209,8 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	private Optional<Path> sourceFile = Optional.empty();
 	private Optional<IRI> sourceIri = Optional.empty();
 	private Consumer<Quad> target;
+	private Optional<Dataset> targetDataset;
+	private Optional<Graph> targetGraph;
 
 	@Override
 	public AbstractRDFParserBuilder clone() {
@@ -319,6 +358,22 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 		sourceFile = Optional.empty();
 	}
 
+
+	/**
+	 * Reset all optional target* fields to Optional.empty()</code>
+	 * <p>
+	 * Note that the consumer set for {@link #getTarget()} is
+	 * NOT reset.
+	 * <p>
+	 * Subclasses should override this and call <code>super.resetTarget()</code>
+	 * if they need to reset any additional target* fields.
+	 * 
+	 */
+	protected void resetTarget() {
+		targetDataset = Optional.empty();
+		targetGraph = Optional.empty();
+	}	
+	
 	/**
 	 * Parse {@link #sourceInputStream}, {@link #sourceFile} or
 	 * {@link #sourceIri}.
@@ -387,6 +442,10 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 		if (target == null) {
 			throw new IllegalStateException("target has not been set");
 		}
+		if (targetGraph.isPresent() && targetDataset.isPresent()) {
+			// This should not happen as each target(..) method resets the optionals
+			throw new IllegalStateException("targetGraph and targetDataset can't both be set");
+		}
 	}
 
 	/**
@@ -470,8 +529,27 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	@Override
 	public RDFParserBuilder target(Consumer<Quad> consumer) {
 		AbstractRDFParserBuilder c = clone();
+		c.resetTarget();
 		c.target = consumer;
 		return c;
 	}
+	
+	@Override
+	public RDFParserBuilder target(Dataset dataset) {
+		AbstractRDFParserBuilder c = (AbstractRDFParserBuilder) RDFParserBuilder.super.target(dataset);
+		c.resetTarget();
+		c.targetDataset = Optional.of(dataset);
+		return c;
+	}
+	
+	@Override
+	public RDFParserBuilder target(Graph graph) {
+		AbstractRDFParserBuilder c = (AbstractRDFParserBuilder) RDFParserBuilder.super.target(graph);
+		c.resetTarget();
+		c.targetGraph = Optional.of(graph);
+		return c;
+	}
+	
+
 
 }


[09/36] incubator-commonsrdf git commit: Test AbstractRDFParserBuilder

Posted by st...@apache.org.
Test AbstractRDFParserBuilder


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/8dfc3f4e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/8dfc3f4e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/8dfc3f4e

Branch: refs/heads/master
Commit: 8dfc3f4eef9afda61cecf088be42c8a9ee547865
Parents: 8d548d5
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Sun Apr 3 00:22:48 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Sun Apr 3 00:22:48 2016 +0100

----------------------------------------------------------------------
 .../simple/AbstractRDFParserBuilderTest.java    | 67 ++++++++++++++++++++
 .../rdf/simple/DummyRDFParserBuilder.java       | 60 ++++++++++++++++++
 2 files changed, 127 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/8dfc3f4e/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java
----------------------------------------------------------------------
diff --git a/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java b/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java
new file mode 100644
index 0000000..1b751fa
--- /dev/null
+++ b/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java
@@ -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.commons.rdf.simple;
+
+import static org.junit.Assert.*;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.rdf.api.Graph;
+import org.apache.commons.rdf.api.IRI;
+import org.apache.commons.rdf.api.Literal;
+import org.apache.commons.rdf.api.RDFParserBuilder;
+import org.apache.commons.rdf.api.RDFSyntax;
+import org.apache.commons.rdf.api.Triple;
+import org.junit.Test;
+
+public class AbstractRDFParserBuilderTest {
+
+	/**
+	 * Test a basic parsing of an N-Triples-file
+	 * 
+	 * @throws Exception
+	 */
+	@Test
+	public void parseFile() throws Exception {		
+		Path file = Files.createTempFile("test", ".nt");
+		// No need to populate the file as the dummy parser
+		// doesn't actually read anything
+		
+		RDFParserBuilder parser = new DummyRDFParserBuilder()
+				.source(file).contentType(RDFSyntax.NTRIPLES);
+		Future<Graph> f = parser.parse();
+		Graph g = f.get(5, TimeUnit.SECONDS);
+		
+		assertEquals(1, g.size());
+		Triple triple = g.getTriples().findAny().get();
+		assertTrue(triple.getSubject() instanceof IRI);
+		IRI iri = (IRI)triple.getSubject();
+		assertEquals("http://example.com/test1", iri.getIRIString());
+		
+		assertEquals("http://example.com/greeting", triple.getPredicate().getIRIString());
+		
+		assertTrue(triple.getObject() instanceof Literal);
+		Literal literal = (Literal)triple.getObject();
+		assertEquals("Hello world", literal.getLexicalForm());
+		assertFalse(literal.getLanguageTag().isPresent());
+		assertEquals(Types.XSD_STRING, literal.getDatatype());
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/8dfc3f4e/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java b/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
new file mode 100644
index 0000000..38e6ed2
--- /dev/null
+++ b/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
@@ -0,0 +1,60 @@
+/**
+ * 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.commons.rdf.simple;
+
+import java.io.IOException;
+import java.text.ParseException;
+
+import org.apache.commons.rdf.api.Graph;
+import org.apache.commons.rdf.api.IRI;
+import org.apache.commons.rdf.api.Literal;
+import org.apache.commons.rdf.api.RDFParserBuilder;
+import org.apache.commons.rdf.api.RDFTermFactory;
+
+/** 
+ * For test purposes - a {@link RDFParserBuilder} that always insert a single triple.
+ * <p>
+ * This dummy RDF parser always sleeps for at least 1000 ms
+ * before inserting the triple:
+ * <pre>
+ *    <http://example.com/test1> <http://example.com/greeting> "Hello world" .
+ * </pre>
+ *
+ */
+public class DummyRDFParserBuilder extends AbstractRDFParserBuilder {
+
+	@Override
+	protected void parseSynchronusly() throws IOException, IllegalStateException, ParseException {		
+		// From parseSynchronusly both of these are always present
+		RDFTermFactory factory = getRdfTermFactory().get();
+		Graph graph = getIntoGraph().get();
+		
+		// Let's always insert the same triple
+		IRI test1 = factory.createIRI("http://example.com/test1");
+		IRI greeting = factory.createIRI("http://example.com/greeting");
+		Literal hello = factory.createLiteral("Hello world");
+		try {
+			// Pretend we take a while to parse
+			Thread.sleep(1000);			
+		} catch (InterruptedException e) {
+			return;
+		} 
+		graph.add(test1, greeting, hello); 		
+	}
+
+}


[20/36] incubator-commonsrdf git commit: Merge branch 'quad' into parser-with-quads

Posted by st...@apache.org.
Merge branch 'quad' into parser-with-quads


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/bb90a6ea
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/bb90a6ea
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/bb90a6ea

Branch: refs/heads/master
Commit: bb90a6ea22374d49c4e6d38e07ff98e0c8803b7b
Parents: d153b4c 839a642
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Wed Apr 13 15:35:01 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Wed Apr 13 15:35:01 2016 +0100

----------------------------------------------------------------------
 .../org/apache/commons/rdf/api/Dataset.java     | 338 +++++++++++++++++++
 .../java/org/apache/commons/rdf/api/Quad.java   | 207 ++++++++++++
 .../apache/commons/rdf/api/RDFTermFactory.java  |  40 +++
 .../java/org/apache/commons/rdf/api/Triple.java |   2 +-
 .../apache/commons/rdf/api/TripleOrQuad.java    |  64 ++++
 .../commons/rdf/simple/BlankNodeImpl.java       |   3 +-
 .../apache/commons/rdf/simple/DatasetImpl.java  | 226 +++++++++++++
 .../apache/commons/rdf/simple/GraphImpl.java    |  18 +-
 .../org/apache/commons/rdf/simple/IRIImpl.java  |   2 +-
 .../apache/commons/rdf/simple/LiteralImpl.java  |   2 +-
 .../org/apache/commons/rdf/simple/QuadImpl.java | 109 ++++++
 .../rdf/simple/SimpleRDFTermFactory.java        |  25 ++
 .../org/apache/commons/rdf/simple/Types.java    |   2 +-
 13 files changed, 1026 insertions(+), 12 deletions(-)
----------------------------------------------------------------------



[35/36] incubator-commonsrdf git commit: COMMONSRDF-39 experimental RDFParser interface

Posted by st...@apache.org.
COMMONSRDF-39 experimental RDFParser interface

moved to org.apache.commons.rdf.experimental for now


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/10d27cde
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/10d27cde
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/10d27cde

Branch: refs/heads/master
Commit: 10d27cde2f7310a68274eacf550f201a3690dab8
Parents: bfcead4
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Wed Sep 28 14:16:02 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Wed Sep 28 14:16:02 2016 +0100

----------------------------------------------------------------------
 .../commons/rdf/api/RDFParserBuilder.java       | 479 ----------------
 .../commons/rdf/experimental/RDFParser.java     | 495 +++++++++++++++++
 .../commons/rdf/experimental/package-info.java  |  34 ++
 .../test/resources/example-rdf/example.jsonld   |  25 +
 api/src/test/resources/example-rdf/example.nq   |   3 +
 api/src/test/resources/example-rdf/example.nt   |   2 +
 api/src/test/resources/example-rdf/example.rdf  |  23 +
 api/src/test/resources/example-rdf/example.trig |   3 +
 api/src/test/resources/example-rdf/example.ttl  |   2 +
 .../rdf/simple/AbstractRDFParserBuilder.java    | 541 ------------------
 .../commons/rdf/simple/RDFParseException.java   |  50 --
 .../simple/experimental/AbstractRDFParser.java  | 542 +++++++++++++++++++
 .../simple/experimental/RDFParseException.java  |  50 ++
 .../rdf/simple/experimental/package-info.java   |  34 ++
 .../simple/AbstractRDFParserBuilderTest.java    | 253 ---------
 .../rdf/simple/DummyRDFParserBuilder.java       |  12 +-
 .../experimental/AbstractRDFParserTest.java     | 256 +++++++++
 17 files changed, 1476 insertions(+), 1328 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
deleted file mode 100644
index dde92ac..0000000
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ /dev/null
@@ -1,479 +0,0 @@
-/**
- * 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.commons.rdf.api;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Path;
-import java.util.Optional;
-import java.util.concurrent.Future;
-import java.util.function.Consumer;
-
-/**
- * Builder for parsing an RDF source into a target (e.g. a Graph/Dataset).
- * <p>
- * This interface follows the
- * <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder pattern</a>,
- * allowing to set parser settings like {@link #contentType(RDFSyntax)} and
- * {@link #base(IRI)}. A caller MUST call one of the <code>source</code> methods
- * (e.g. {@link #source(IRI)}, {@link #source(Path)},
- * {@link #source(InputStream)}), and MUST call one of the <code>target</code>
- * methods (e.g. {@link #target(Consumer)}, {@link #target(Dataset)},
- * {@link #target(Graph)}) before calling {@link #parse()} on the returned
- * RDFParserBuilder - however methods can be called in any order.
- * <p>
- * The call to {@link #parse()} returns a {@link Future}, allowing asynchronous
- * parse operations. Callers are recommended to check {@link Future#get()} to
- * ensure parsing completed successfully, or catch exceptions thrown during
- * parsing.
- * <p>
- * Setting a method that has already been set will override any existing value
- * in the returned builder - regardless of the parameter type (e.g.
- * {@link #source(IRI)} will override a previous {@link #source(Path)}. Settings
- * can be unset by passing <code>null</code> - note that this may 
- * require casting, e.g. <code>contentType( (RDFSyntax) null )</code> 
- * to undo a previous call to {@link #contentType(RDFSyntax)}.
- * <p>
- * It is undefined if a RDFParserBuilder is mutable or thread-safe, so callers
- * should always use the returned modified RDFParserBuilder from the builder
- * methods. The builder may return itself after modification, 
- * or a cloned builder with the modified settings applied. 
- * Implementations are however encouraged to be immutable,
- * thread-safe and document this. As an example starting point, see
- * {@link org.apache.commons.rdf.simple.AbstractRDFParserBuilder}.
- * <p>
- * Example usage:
- * </p>
- * 
- * <pre>
- *   Graph g1 = rDFTermFactory.createGraph();
- *   new ExampleRDFParserBuilder()
- *    	.source(Paths.get("/tmp/graph.ttl"))
- *    	.contentType(RDFSyntax.TURTLE)
- *   	.target(g1)
- *   	.parse().get(30, TimeUnit.Seconds);
- * </pre>
- *
- */
-public interface RDFParserBuilder {
-
-	/** 
-	 * The result of {@link RDFParserBuilder#parse()} indicating
-	 * parsing completed.
-	 * <p>
-	 * This is a marker interface that may be subclassed to include
-	 * parser details, e.g. warning messages or triple counts.
-	 */
-	public interface ParseResult {		
-	}
-
-	/**
-	 * Specify which {@link RDFTermFactory} to use for generating
-	 * {@link RDFTerm}s.
-	 * <p>
-	 * This option may be used together with {@link #target(Graph)} to
-	 * override the implementation's default factory and graph.
-	 * <p>
-	 * <strong>Warning:</strong> Using the same {@link RDFTermFactory} for 
-	 * multiple {@link #parse()} calls  may accidentally merge 
-	 * {@link BlankNode}s having the same label, as the parser may 
-	 * use the {@link RDFTermFactory#createBlankNode(String)} method
-	 * from the parsed blank node labels.
-	 * 
-	 * @see #target(Graph)
-	 * @param rdfTermFactory
-	 *            {@link RDFTermFactory} to use for generating RDFTerms.
-	 * @return An {@link RDFParserBuilder} that will use the specified
-	 *         rdfTermFactory
-	 */
-	RDFParserBuilder rdfTermFactory(RDFTermFactory rdfTermFactory);
-
-	/**
-	 * Specify the content type of the RDF syntax to parse.
-	 * <p>
-	 * This option can be used to select the RDFSyntax of the source, overriding
-	 * any <code>Content-Type</code> headers or equivalent.
-	 * <p>
-	 * The character set of the RDFSyntax is assumed to be
-	 * {@link StandardCharsets#UTF_8} unless overridden within the document
-	 * (e.g. <?xml version="1.0" encoding="iso-8859-1"?></code> in
-	 * {@link RDFSyntax#RDFXML}).
-	 * <p>
-	 * This method will override any contentType set with
-	 * {@link #contentType(String)}.
-	 * 
-	 * @see #contentType(String)
-	 * @param rdfSyntax
-	 *            An {@link RDFSyntax} to parse the source according to, e.g.
-	 *            {@link RDFSyntax#TURTLE}.
-	 * @throws IllegalArgumentException
-	 *             If this RDFParserBuilder does not support the specified
-	 *             RDFSyntax.
-	 * @return An {@link RDFParserBuilder} that will use the specified content
-	 *         type.
-	 */
-	RDFParserBuilder contentType(RDFSyntax rdfSyntax) throws IllegalArgumentException;
-
-	/**
-	 * Specify the content type of the RDF syntax to parse.
-	 * <p>
-	 * This option can be used to select the RDFSyntax of the source, overriding
-	 * any <code>Content-Type</code> headers or equivalent.
-	 * <p>
-	 * The content type MAY include a <code>charset</code> parameter if the RDF
-	 * media types permit it; the default charset is
-	 * {@link StandardCharsets#UTF_8} unless overridden within the document.
-	 * <p>
-	 * This method will override any contentType set with
-	 * {@link #contentType(RDFSyntax)}.
-	 * 
-	 * @see #contentType(RDFSyntax)
-	 * @param contentType
-	 *            A content-type string, e.g. <code>application/ld+json</code>
-	 *            or <code>text/turtle;charset="UTF-8"</code> as specified by
-	 *            <a href="https://tools.ietf.org/html/rfc7231#section-3.1.1.1">
-	 *            RFC7231</a>.
-	 * @return An {@link RDFParserBuilder} that will use the specified content
-	 *         type.
-	 * @throws IllegalArgumentException
-	 *             If the contentType has an invalid syntax, or this
-	 *             RDFParserBuilder does not support the specified contentType.
-	 */
-	RDFParserBuilder contentType(String contentType) throws IllegalArgumentException;
-
-	/**
-	 * Specify a {@link Graph} to add parsed triples to.
-	 * <p>
-	 * If the source supports datasets (e.g. the {@link #contentType(RDFSyntax)}
-	 * set has {@link RDFSyntax#supportsDataset} is true)), then only quads in
-	 * the <em>default graph</em> will be added to the Graph as {@link Triple}s.
-	 * <p>
-	 * It is undefined if any triples are added to the specified {@link Graph}
-	 * if {@link #parse()} throws any exceptions. (However implementations are
-	 * free to prevent this using transaction mechanisms or similar). If
-	 * {@link Future#get()} does not indicate an exception, the parser
-	 * implementation SHOULD have inserted all parsed triples to the specified
-	 * graph.
-	 * <p>
-	 * Calling this method will override any earlier targets set with
-	 * {@link #target(Graph)}, {@link #target(Consumer)} or
-	 * {@link #target(Dataset)}.
-	 * <p>
-	 * The default implementation of this method calls {@link #target(Consumer)}
-	 * with a {@link Consumer} that does {@link Graph#add(Triple)} with
-	 * {@link Quad#asTriple()} if the quad is in the default graph.
-	 * 
-	 * @param graph
-	 *            The {@link Graph} to add triples to.
-	 * @return An {@link RDFParserBuilder} that will insert triples into the
-	 *         specified graph.
-	 */
-	default RDFParserBuilder target(Graph graph) {		
-		return target(q -> { 
-			if (! q.getGraphName().isPresent()) { 
-				graph.add(q.asTriple());
-			}
-		});
-	}
-
-	/**
-	 * Specify a {@link Dataset} to add parsed quads to.
-	 * <p>
-	 * It is undefined if any quads are added to the specified
-	 * {@link Dataset} if {@link #parse()} throws any exceptions. 
-	 * (However implementations are free to prevent this using transaction 
-	 * mechanisms or similar).  On the other hand, if {@link #parse()}
-	 * does not indicate an exception, the 
-	 * implementation SHOULD have inserted all parsed quads 
-	 * to the specified dataset.
-	 * <p>
-	 * Calling this method will override any earlier targets set with 
-	 * {@link #target(Graph)}, {@link #target(Consumer)} or {@link #target(Dataset)}.
-	 * <p>
-	 * The default implementation of this method calls {@link #target(Consumer)}
-	 * with a {@link Consumer} that does {@link Dataset#add(Quad)}.
-	 * 
-	 * @param dataset
-	 *            The {@link Dataset} to add quads to.
-	 * @return An {@link RDFParserBuilder} that will insert triples into the
-	 *         specified dataset.
-	 */
-	default RDFParserBuilder target(Dataset dataset) {
-		return target(dataset::add);
-	}
-
-	/**
-	 * Specify a consumer for parsed quads.
-	 * <p>
-	 * The quads will include triples in all named graphs of the parsed 
-	 * source, including any triples in the default graph. 
-	 * When parsing a source format which do not support datasets, all quads 
-	 * delivered to the consumer will be in the default graph 
-	 * (e.g. their {@link Quad#getGraphName()} will be
-	 * as {@link Optional#empty()}), while for a source   
-	 * <p>
-	 * It is undefined if any quads are consumed if {@link #parse()} throws any
-	 * exceptions. On the other hand, if {@link #parse()} does not indicate an
-	 * exception, the implementation SHOULD have produced all parsed quads to
-	 * the specified consumer.
-	 * <p>
-	 * Calling this method will override any earlier targets set with
-	 * {@link #target(Graph)}, {@link #target(Consumer)} or
-	 * {@link #target(Dataset)}.
-	 * <p>
-	 * The consumer is not assumed to be thread safe - only one
-	 * {@link Consumer#accept(Object)} is delivered at a time for a given
-	 * {@link RDFParserBuilder#parse()} call.
-	 * <p>
-	 * This method is typically called with a functional consumer, for example:
-	 * <pre>
-	 * List<Quad> quads = new ArrayList<Quad>;
-	 * parserBuilder.target(quads::add).parse();
-	 * </pre>
-	 * 
-	 * @param consumer
-	 *            A {@link Consumer} of {@link Quad}s
-	 * @return An {@link RDFParserBuilder} that will call the consumer for into
-	 *         the specified dataset.
-	 */
-	RDFParserBuilder target(Consumer<Quad> consumer);
-	
-	/**
-	 * Specify a base IRI to use for parsing any relative IRI references.
-	 * <p>
-	 * Setting this option will override any protocol-specific base IRI (e.g.
-	 * <code>Content-Location</code> header) or the {@link #source(IRI)} IRI,
-	 * but does not override any base IRIs set within the source document (e.g.
-	 * <code>@base</code> in Turtle documents).
-	 * <p>
-	 * If the source is in a syntax that does not support relative IRI
-	 * references (e.g. {@link RDFSyntax#NTRIPLES}), setting the
-	 * <code>base</code> has no effect.
-	 * <p>
-	 * This method will override any base IRI set with {@link #base(String)}.
-	 *
-	 * @see #base(String)
-	 * @param base
-	 *            An absolute IRI to use as a base.
-	 * @return An {@link RDFParserBuilder} that will use the specified base IRI.
-	 */
-	RDFParserBuilder base(IRI base);
-
-	/**
-	 * Specify a base IRI to use for parsing any relative IRI references.
-	 * <p>
-	 * Setting this option will override any protocol-specific base IRI (e.g.
-	 * <code>Content-Location</code> header) or the {@link #source(IRI)} IRI,
-	 * but does not override any base IRIs set within the source document (e.g.
-	 * <code>@base</code> in Turtle documents).
-	 * <p>
-	 * If the source is in a syntax that does not support relative IRI
-	 * references (e.g. {@link RDFSyntax#NTRIPLES}), setting the
-	 * <code>base</code> has no effect.
-	 * <p>
-	 * This method will override any base IRI set with {@link #base(IRI)}.
-	 *
-	 * @see #base(IRI)
-	 * @param base
-	 *            An absolute IRI to use as a base.
-	 * @return An {@link RDFParserBuilder} that will use the specified base IRI.
-	 * @throws IllegalArgumentException
-	 *             If the base is not a valid absolute IRI string
-	 */
-	RDFParserBuilder base(String base) throws IllegalArgumentException;
-
-	/**
-	 * Specify a source {@link InputStream} to parse.
-	 * <p>
-	 * The source set will not be read before the call to {@link #parse()}.
-	 * <p>
-	 * The InputStream will not be closed after parsing. The InputStream does
-	 * not need to support {@link InputStream#markSupported()}.
-	 * <p>
-	 * The parser might not consume the complete stream (e.g. an RDF/XML parser
-	 * may not read beyond the closing tag of
-	 * <code>&lt;/rdf:Description&gt;</code>).
-	 * <p>
-	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)}
-	 * SHOULD be set before calling {@link #parse()}.
-	 * <p>
-	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
-	 * the {@link #contentType(String)} specifies otherwise or the document
-	 * declares its own charset (e.g. RDF/XML with a
-	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
-	 * <p>
-	 * The {@link #base(IRI)} or {@link #base(String)} MUST be set before
-	 * calling {@link #parse()}, unless the RDF syntax does not permit relative
-	 * IRIs (e.g. {@link RDFSyntax#NTRIPLES}).
-	 * <p>
-	 * This method will override any source set with {@link #source(IRI)},
-	 * {@link #source(Path)} or {@link #source(String)}.
-	 * 
-	 * @param inputStream
-	 *            An InputStream to consume
-	 * @return An {@link RDFParserBuilder} that will use the specified source.
-	 */
-	RDFParserBuilder source(InputStream inputStream);
-
-	/**
-	 * Specify a source file {@link Path} to parse.
-	 * <p>
-	 * The source set will not be read before the call to {@link #parse()}.
-	 * <p>
-	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)}
-	 * SHOULD be set before calling {@link #parse()}.
-	 * <p>
-	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
-	 * the {@link #contentType(String)} specifies otherwise or the document
-	 * declares its own charset (e.g. RDF/XML with a
-	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
-	 * <p>
-	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before calling
-	 * {@link #parse()}, otherwise {@link Path#toUri()} will be used as the base
-	 * IRI.
-	 * <p>
-	 * This method will override any source set with {@link #source(IRI)},
-	 * {@link #source(InputStream)} or {@link #source(String)}.
-	 * 
-	 * @param file
-	 *            A Path for a file to parse
-	 * @return An {@link RDFParserBuilder} that will use the specified source.
-	 */
-	RDFParserBuilder source(Path file);
-
-	/**
-	 * Specify an absolute source {@link IRI} to retrieve and parse.
-	 * <p>
-	 * The source set will not be read before the call to {@link #parse()}.
-	 * <p>
-	 * If this builder does not support the given IRI protocol (e.g.
-	 * <code>urn:uuid:ce667463-c5ab-4c23-9b64-701d055c4890</code>), this method
-	 * should succeed, while the {@link #parse()} should throw an
-	 * {@link IOException}.
-	 * <p>
-	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)} MAY
-	 * be set before calling {@link #parse()}, in which case that type MAY be
-	 * used for content negotiation (e.g. <code>Accept</code> header in HTTP),
-	 * and SHOULD be used for selecting the RDFSyntax.
-	 * <p>
-	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
-	 * the protocol's equivalent of <code>Content-Type</code> specifies
-	 * otherwise or the document declares its own charset (e.g. RDF/XML with a
-	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
-	 * <p>
-	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before calling
-	 * {@link #parse()}, otherwise the source IRI will be used as the base IRI.
-	 * <p>
-	 * This method will override any source set with {@link #source(Path)},
-	 * {@link #source(InputStream)} or {@link #source(String)}.
-	 * 
-	 * @param iri
-	 *            An IRI to retrieve and parse
-	 * @return An {@link RDFParserBuilder} that will use the specified source.
-	 */
-	RDFParserBuilder source(IRI iri);
-
-	/**
-	 * Specify an absolute source IRI to retrieve and parse.
-	 * <p>
-	 * The source set will not be read before the call to {@link #parse()}.
-	 * <p>
-	 * If this builder does not support the given IRI (e.g.
-	 * <code>urn:uuid:ce667463-c5ab-4c23-9b64-701d055c4890</code>), this method
-	 * should succeed, while the {@link #parse()} should throw an
-	 * {@link IOException}.
-	 * <p>
-	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)} MAY
-	 * be set before calling {@link #parse()}, in which case that type MAY be
-	 * used for content negotiation (e.g. <code>Accept</code> header in HTTP),
-	 * and SHOULD be used for selecting the RDFSyntax.
-	 * <p>
-	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
-	 * the protocol's equivalent of <code>Content-Type</code> specifies
-	 * otherwise or the document declares its own charset (e.g. RDF/XML with a
-	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
-	 * <p>
-	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before calling
-	 * {@link #parse()}, otherwise the source IRI will be used as the base IRI.
-	 * <p>
-	 * This method will override any source set with {@link #source(Path)},
-	 * {@link #source(InputStream)} or {@link #source(IRI)}.
-	 * 
-	 * @param iri
-	 *            An IRI to retrieve and parse
-	 * @return An {@link RDFParserBuilder} that will use the specified source.
-	 * @throws IllegalArgumentException
-	 *             If the base is not a valid absolute IRI string
-	 * 
-	 */
-	RDFParserBuilder source(String iri) throws IllegalArgumentException;
-
-	/**
-	 * Parse the specified source.
-	 * <p>
-	 * A source method (e.g. {@link #source(InputStream)}, {@link #source(IRI)},
-	 * {@link #source(Path)}, {@link #source(String)} or an equivalent subclass
-	 * method) MUST have been called before calling this method, otherwise an
-	 * {@link IllegalStateException} will be thrown.
-	 * <p>
-	 * A target method (e.g. {@link #target(Consumer)}, {@link #target(Dataset)},
-	 * {@link #target(Graph)} or an equivalent subclass method) MUST have been
-	 * called before calling parse(), otherwise an
-	 * {@link IllegalStateException} will be thrown.
-	 * <p>
-	 * It is undefined if this method is thread-safe, however the
-	 * {@link RDFParserBuilder} may be reused (e.g. setting a different source)
-	 * as soon as the {@link Future} has been returned from this method.
-	 * <p>
-	 * The RDFParserBuilder SHOULD perform the parsing as an asynchronous
-	 * operation, and return the {@link Future} as soon as preliminary checks
-	 * (such as validity of the {@link #source(IRI)} and
-	 * {@link #contentType(RDFSyntax)} settings) have finished. The future
-	 * SHOULD not mark {@link Future#isDone()} before parsing is complete. A
-	 * synchronous implementation MAY be blocking on the <code>parse()</code>
-	 * call and return a Future that is already {@link Future#isDone()}.
-	 * <p>
-	 * The returned {@link Future} contains a {@link ParseResult}. 
-	 * Implementations may subclass this interface to provide any 
-	 * parser details, e.g. list of warnings. <code>null</code> is a
-	 * possible return value if no details are available, but 
-	 * parsing succeeded.
-	 * <p>
-	 * If an exception occurs during parsing, (e.g. {@link IOException} or
-	 * {@link org.apache.commons.rdf.simple.RDFParseException}), 
-	 * it should be indicated as the
-	 * {@link java.util.concurrent.ExecutionException#getCause()} in the
-	 * {@link java.util.concurrent.ExecutionException} thrown on
-	 * {@link Future#get()}.
-	 * 
-	 * @return A Future that will return the populated {@link Graph} when the
-	 *         parsing has finished.
-	 * @throws IOException
-	 *             If an error occurred while starting to read the source (e.g.
-	 *             file not found, unsupported IRI protocol). Note that IO
-	 *             errors during parsing would instead be the
-	 *             {@link java.util.concurrent.ExecutionException#getCause()} of
-	 *             the {@link java.util.concurrent.ExecutionException} thrown on
-	 *             {@link Future#get()}.
-	 * @throws IllegalStateException
-	 *             If the builder is in an invalid state, e.g. a
-	 *             <code>source</code> has not been set.
-	 */
-	Future<? extends ParseResult> parse() throws IOException, IllegalStateException;
-}

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/api/src/main/java/org/apache/commons/rdf/experimental/RDFParser.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/experimental/RDFParser.java b/api/src/main/java/org/apache/commons/rdf/experimental/RDFParser.java
new file mode 100644
index 0000000..dd6bcf0
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/experimental/RDFParser.java
@@ -0,0 +1,495 @@
+/**
+ * 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.commons.rdf.experimental;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.util.Optional;
+import java.util.concurrent.Future;
+import java.util.function.Consumer;
+
+import org.apache.commons.rdf.api.BlankNode;
+import org.apache.commons.rdf.api.Dataset;
+import org.apache.commons.rdf.api.Graph;
+import org.apache.commons.rdf.api.IRI;
+import org.apache.commons.rdf.api.Quad;
+import org.apache.commons.rdf.api.RDFSyntax;
+import org.apache.commons.rdf.api.RDFTerm;
+import org.apache.commons.rdf.api.RDFTermFactory;
+import org.apache.commons.rdf.api.Triple;
+
+/**
+ * Parse an RDF source into a target (e.g. a Graph/Dataset).
+ * <h2>Experimental</h2>
+ * This interface (and its implementations) should be considered <strong>at
+ * risk</strong>; they might change or be removed in the next minor update of
+ * Commons RDF. It may move to the the  {@link org.apache.commons.rdf.api}
+ * package when it has stabilized.
+ * <h2>Description</h2>
+ * <p>
+ * This interface follows the
+ * <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder pattern</a>,
+ * allowing to set parser settings like {@link #contentType(RDFSyntax)} and
+ * {@link #base(IRI)}. A caller MUST call one of the <code>source</code> methods
+ * (e.g. {@link #source(IRI)}, {@link #source(Path)},
+ * {@link #source(InputStream)}), and MUST call one of the <code>target</code>
+ * methods (e.g. {@link #target(Consumer)}, {@link #target(Dataset)},
+ * {@link #target(Graph)}) before calling {@link #parse()} on the returned
+ * RDFParser - however methods can be called in any order.
+ * <p>
+ * The call to {@link #parse()} returns a {@link Future}, allowing asynchronous
+ * parse operations. Callers are recommended to check {@link Future#get()} to
+ * ensure parsing completed successfully, or catch exceptions thrown during
+ * parsing.
+ * <p>
+ * Setting a method that has already been set will override any existing value
+ * in the returned builder - regardless of the parameter type (e.g.
+ * {@link #source(IRI)} will override a previous {@link #source(Path)}. Settings
+ * can be unset by passing <code>null</code> - note that this may 
+ * require casting, e.g. <code>contentType( (RDFSyntax) null )</code> 
+ * to undo a previous call to {@link #contentType(RDFSyntax)}.
+ * <p>
+ * It is undefined if a RDFParser is mutable or thread-safe, so callers
+ * should always use the returned modified RDFParser from the builder
+ * methods. The builder may return itself after modification, 
+ * or a cloned builder with the modified settings applied. 
+ * Implementations are however encouraged to be immutable,
+ * thread-safe and document this. As an example starting point, see
+ * {@link org.apache.commons.rdf.simple.AbstractRDFParserBuilder}.
+ * <p>
+ * Example usage:
+ * </p>
+ * 
+ * <pre>
+ *   Graph g1 = rDFTermFactory.createGraph();
+ *   new ExampleRDFParserBuilder()
+ *    	.source(Paths.get("/tmp/graph.ttl"))
+ *    	.contentType(RDFSyntax.TURTLE)
+ *   	.target(g1)
+ *   	.parse().get(30, TimeUnit.Seconds);
+ * </pre>
+ *
+ */
+public interface RDFParser {
+
+	/** 
+	 * The result of {@link RDFParser#parse()} indicating
+	 * parsing completed.
+	 * <p>
+	 * This is a marker interface that may be subclassed to include
+	 * parser details, e.g. warning messages or triple counts.
+	 */
+	public interface ParseResult {		
+	}
+
+	/**
+	 * Specify which {@link RDFTermFactory} to use for generating
+	 * {@link RDFTerm}s.
+	 * <p>
+	 * This option may be used together with {@link #target(Graph)} to
+	 * override the implementation's default factory and graph.
+	 * <p>
+	 * <strong>Warning:</strong> Using the same {@link RDFTermFactory} for 
+	 * multiple {@link #parse()} calls  may accidentally merge 
+	 * {@link BlankNode}s having the same label, as the parser may 
+	 * use the {@link RDFTermFactory#createBlankNode(String)} method
+	 * from the parsed blank node labels.
+	 * 
+	 * @see #target(Graph)
+	 * @param rdfTermFactory
+	 *            {@link RDFTermFactory} to use for generating RDFTerms.
+	 * @return An {@link RDFParser} that will use the specified
+	 *         rdfTermFactory
+	 */
+	RDFParser rdfTermFactory(RDFTermFactory rdfTermFactory);
+
+	/**
+	 * Specify the content type of the RDF syntax to parse.
+	 * <p>
+	 * This option can be used to select the RDFSyntax of the source, overriding
+	 * any <code>Content-Type</code> headers or equivalent.
+	 * <p>
+	 * The character set of the RDFSyntax is assumed to be
+	 * {@link StandardCharsets#UTF_8} unless overridden within the document
+	 * (e.g. <?xml version="1.0" encoding="iso-8859-1"?></code> in
+	 * {@link RDFSyntax#RDFXML}).
+	 * <p>
+	 * This method will override any contentType set with
+	 * {@link #contentType(String)}.
+	 * 
+	 * @see #contentType(String)
+	 * @param rdfSyntax
+	 *            An {@link RDFSyntax} to parse the source according to, e.g.
+	 *            {@link RDFSyntax#TURTLE}.
+	 * @throws IllegalArgumentException
+	 *             If this RDFParser does not support the specified
+	 *             RDFSyntax.
+	 * @return An {@link RDFParser} that will use the specified content
+	 *         type.
+	 */
+	RDFParser contentType(RDFSyntax rdfSyntax) throws IllegalArgumentException;
+
+	/**
+	 * Specify the content type of the RDF syntax to parse.
+	 * <p>
+	 * This option can be used to select the RDFSyntax of the source, overriding
+	 * any <code>Content-Type</code> headers or equivalent.
+	 * <p>
+	 * The content type MAY include a <code>charset</code> parameter if the RDF
+	 * media types permit it; the default charset is
+	 * {@link StandardCharsets#UTF_8} unless overridden within the document.
+	 * <p>
+	 * This method will override any contentType set with
+	 * {@link #contentType(RDFSyntax)}.
+	 * 
+	 * @see #contentType(RDFSyntax)
+	 * @param contentType
+	 *            A content-type string, e.g. <code>application/ld+json</code>
+	 *            or <code>text/turtle;charset="UTF-8"</code> as specified by
+	 *            <a href="https://tools.ietf.org/html/rfc7231#section-3.1.1.1">
+	 *            RFC7231</a>.
+	 * @return An {@link RDFParser} that will use the specified content
+	 *         type.
+	 * @throws IllegalArgumentException
+	 *             If the contentType has an invalid syntax, or this
+	 *             RDFParser does not support the specified contentType.
+	 */
+	RDFParser contentType(String contentType) throws IllegalArgumentException;
+
+	/**
+	 * Specify a {@link Graph} to add parsed triples to.
+	 * <p>
+	 * If the source supports datasets (e.g. the {@link #contentType(RDFSyntax)}
+	 * set has {@link RDFSyntax#supportsDataset} is true)), then only quads in
+	 * the <em>default graph</em> will be added to the Graph as {@link Triple}s.
+	 * <p>
+	 * It is undefined if any triples are added to the specified {@link Graph}
+	 * if {@link #parse()} throws any exceptions. (However implementations are
+	 * free to prevent this using transaction mechanisms or similar). If
+	 * {@link Future#get()} does not indicate an exception, the parser
+	 * implementation SHOULD have inserted all parsed triples to the specified
+	 * graph.
+	 * <p>
+	 * Calling this method will override any earlier targets set with
+	 * {@link #target(Graph)}, {@link #target(Consumer)} or
+	 * {@link #target(Dataset)}.
+	 * <p>
+	 * The default implementation of this method calls {@link #target(Consumer)}
+	 * with a {@link Consumer} that does {@link Graph#add(Triple)} with
+	 * {@link Quad#asTriple()} if the quad is in the default graph.
+	 * 
+	 * @param graph
+	 *            The {@link Graph} to add triples to.
+	 * @return An {@link RDFParser} that will insert triples into the
+	 *         specified graph.
+	 */
+	default RDFParser target(Graph graph) {		
+		return target(q -> { 
+			if (! q.getGraphName().isPresent()) { 
+				graph.add(q.asTriple());
+			}
+		});
+	}
+
+	/**
+	 * Specify a {@link Dataset} to add parsed quads to.
+	 * <p>
+	 * It is undefined if any quads are added to the specified
+	 * {@link Dataset} if {@link #parse()} throws any exceptions. 
+	 * (However implementations are free to prevent this using transaction 
+	 * mechanisms or similar).  On the other hand, if {@link #parse()}
+	 * does not indicate an exception, the 
+	 * implementation SHOULD have inserted all parsed quads 
+	 * to the specified dataset.
+	 * <p>
+	 * Calling this method will override any earlier targets set with 
+	 * {@link #target(Graph)}, {@link #target(Consumer)} or {@link #target(Dataset)}.
+	 * <p>
+	 * The default implementation of this method calls {@link #target(Consumer)}
+	 * with a {@link Consumer} that does {@link Dataset#add(Quad)}.
+	 * 
+	 * @param dataset
+	 *            The {@link Dataset} to add quads to.
+	 * @return An {@link RDFParser} that will insert triples into the
+	 *         specified dataset.
+	 */
+	default RDFParser target(Dataset dataset) {
+		return target(dataset::add);
+	}
+
+	/**
+	 * Specify a consumer for parsed quads.
+	 * <p>
+	 * The quads will include triples in all named graphs of the parsed 
+	 * source, including any triples in the default graph. 
+	 * When parsing a source format which do not support datasets, all quads 
+	 * delivered to the consumer will be in the default graph 
+	 * (e.g. their {@link Quad#getGraphName()} will be
+	 * as {@link Optional#empty()}), while for a source   
+	 * <p>
+	 * It is undefined if any quads are consumed if {@link #parse()} throws any
+	 * exceptions. On the other hand, if {@link #parse()} does not indicate an
+	 * exception, the implementation SHOULD have produced all parsed quads to
+	 * the specified consumer.
+	 * <p>
+	 * Calling this method will override any earlier targets set with
+	 * {@link #target(Graph)}, {@link #target(Consumer)} or
+	 * {@link #target(Dataset)}.
+	 * <p>
+	 * The consumer is not assumed to be thread safe - only one
+	 * {@link Consumer#accept(Object)} is delivered at a time for a given
+	 * {@link RDFParser#parse()} call.
+	 * <p>
+	 * This method is typically called with a functional consumer, for example:
+	 * <pre>
+	 * List<Quad> quads = new ArrayList<Quad>;
+	 * parserBuilder.target(quads::add).parse();
+	 * </pre>
+	 * 
+	 * @param consumer
+	 *            A {@link Consumer} of {@link Quad}s
+	 * @return An {@link RDFParser} that will call the consumer for into
+	 *         the specified dataset.
+	 */
+	RDFParser target(Consumer<Quad> consumer);
+	
+	/**
+	 * Specify a base IRI to use for parsing any relative IRI references.
+	 * <p>
+	 * Setting this option will override any protocol-specific base IRI (e.g.
+	 * <code>Content-Location</code> header) or the {@link #source(IRI)} IRI,
+	 * but does not override any base IRIs set within the source document (e.g.
+	 * <code>@base</code> in Turtle documents).
+	 * <p>
+	 * If the source is in a syntax that does not support relative IRI
+	 * references (e.g. {@link RDFSyntax#NTRIPLES}), setting the
+	 * <code>base</code> has no effect.
+	 * <p>
+	 * This method will override any base IRI set with {@link #base(String)}.
+	 *
+	 * @see #base(String)
+	 * @param base
+	 *            An absolute IRI to use as a base.
+	 * @return An {@link RDFParser} that will use the specified base IRI.
+	 */
+	RDFParser base(IRI base);
+
+	/**
+	 * Specify a base IRI to use for parsing any relative IRI references.
+	 * <p>
+	 * Setting this option will override any protocol-specific base IRI (e.g.
+	 * <code>Content-Location</code> header) or the {@link #source(IRI)} IRI,
+	 * but does not override any base IRIs set within the source document (e.g.
+	 * <code>@base</code> in Turtle documents).
+	 * <p>
+	 * If the source is in a syntax that does not support relative IRI
+	 * references (e.g. {@link RDFSyntax#NTRIPLES}), setting the
+	 * <code>base</code> has no effect.
+	 * <p>
+	 * This method will override any base IRI set with {@link #base(IRI)}.
+	 *
+	 * @see #base(IRI)
+	 * @param base
+	 *            An absolute IRI to use as a base.
+	 * @return An {@link RDFParser} that will use the specified base IRI.
+	 * @throws IllegalArgumentException
+	 *             If the base is not a valid absolute IRI string
+	 */
+	RDFParser base(String base) throws IllegalArgumentException;
+
+	/**
+	 * Specify a source {@link InputStream} to parse.
+	 * <p>
+	 * The source set will not be read before the call to {@link #parse()}.
+	 * <p>
+	 * The InputStream will not be closed after parsing. The InputStream does
+	 * not need to support {@link InputStream#markSupported()}.
+	 * <p>
+	 * The parser might not consume the complete stream (e.g. an RDF/XML parser
+	 * may not read beyond the closing tag of
+	 * <code>&lt;/rdf:Description&gt;</code>).
+	 * <p>
+	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)}
+	 * SHOULD be set before calling {@link #parse()}.
+	 * <p>
+	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
+	 * the {@link #contentType(String)} specifies otherwise or the document
+	 * declares its own charset (e.g. RDF/XML with a
+	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
+	 * <p>
+	 * The {@link #base(IRI)} or {@link #base(String)} MUST be set before
+	 * calling {@link #parse()}, unless the RDF syntax does not permit relative
+	 * IRIs (e.g. {@link RDFSyntax#NTRIPLES}).
+	 * <p>
+	 * This method will override any source set with {@link #source(IRI)},
+	 * {@link #source(Path)} or {@link #source(String)}.
+	 * 
+	 * @param inputStream
+	 *            An InputStream to consume
+	 * @return An {@link RDFParser} that will use the specified source.
+	 */
+	RDFParser source(InputStream inputStream);
+
+	/**
+	 * Specify a source file {@link Path} to parse.
+	 * <p>
+	 * The source set will not be read before the call to {@link #parse()}.
+	 * <p>
+	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)}
+	 * SHOULD be set before calling {@link #parse()}.
+	 * <p>
+	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
+	 * the {@link #contentType(String)} specifies otherwise or the document
+	 * declares its own charset (e.g. RDF/XML with a
+	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
+	 * <p>
+	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before calling
+	 * {@link #parse()}, otherwise {@link Path#toUri()} will be used as the base
+	 * IRI.
+	 * <p>
+	 * This method will override any source set with {@link #source(IRI)},
+	 * {@link #source(InputStream)} or {@link #source(String)}.
+	 * 
+	 * @param file
+	 *            A Path for a file to parse
+	 * @return An {@link RDFParser} that will use the specified source.
+	 */
+	RDFParser source(Path file);
+
+	/**
+	 * Specify an absolute source {@link IRI} to retrieve and parse.
+	 * <p>
+	 * The source set will not be read before the call to {@link #parse()}.
+	 * <p>
+	 * If this builder does not support the given IRI protocol (e.g.
+	 * <code>urn:uuid:ce667463-c5ab-4c23-9b64-701d055c4890</code>), this method
+	 * should succeed, while the {@link #parse()} should throw an
+	 * {@link IOException}.
+	 * <p>
+	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)} MAY
+	 * be set before calling {@link #parse()}, in which case that type MAY be
+	 * used for content negotiation (e.g. <code>Accept</code> header in HTTP),
+	 * and SHOULD be used for selecting the RDFSyntax.
+	 * <p>
+	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
+	 * the protocol's equivalent of <code>Content-Type</code> specifies
+	 * otherwise or the document declares its own charset (e.g. RDF/XML with a
+	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
+	 * <p>
+	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before calling
+	 * {@link #parse()}, otherwise the source IRI will be used as the base IRI.
+	 * <p>
+	 * This method will override any source set with {@link #source(Path)},
+	 * {@link #source(InputStream)} or {@link #source(String)}.
+	 * 
+	 * @param iri
+	 *            An IRI to retrieve and parse
+	 * @return An {@link RDFParser} that will use the specified source.
+	 */
+	RDFParser source(IRI iri);
+
+	/**
+	 * Specify an absolute source IRI to retrieve and parse.
+	 * <p>
+	 * The source set will not be read before the call to {@link #parse()}.
+	 * <p>
+	 * If this builder does not support the given IRI (e.g.
+	 * <code>urn:uuid:ce667463-c5ab-4c23-9b64-701d055c4890</code>), this method
+	 * should succeed, while the {@link #parse()} should throw an
+	 * {@link IOException}.
+	 * <p>
+	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)} MAY
+	 * be set before calling {@link #parse()}, in which case that type MAY be
+	 * used for content negotiation (e.g. <code>Accept</code> header in HTTP),
+	 * and SHOULD be used for selecting the RDFSyntax.
+	 * <p>
+	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
+	 * the protocol's equivalent of <code>Content-Type</code> specifies
+	 * otherwise or the document declares its own charset (e.g. RDF/XML with a
+	 * <code>&lt;?xml encoding="iso-8859-1"&gt;</code> header).
+	 * <p>
+	 * The {@link #base(IRI)} or {@link #base(String)} MAY be set before calling
+	 * {@link #parse()}, otherwise the source IRI will be used as the base IRI.
+	 * <p>
+	 * This method will override any source set with {@link #source(Path)},
+	 * {@link #source(InputStream)} or {@link #source(IRI)}.
+	 * 
+	 * @param iri
+	 *            An IRI to retrieve and parse
+	 * @return An {@link RDFParser} that will use the specified source.
+	 * @throws IllegalArgumentException
+	 *             If the base is not a valid absolute IRI string
+	 * 
+	 */
+	RDFParser source(String iri) throws IllegalArgumentException;
+
+	/**
+	 * Parse the specified source.
+	 * <p>
+	 * A source method (e.g. {@link #source(InputStream)}, {@link #source(IRI)},
+	 * {@link #source(Path)}, {@link #source(String)} or an equivalent subclass
+	 * method) MUST have been called before calling this method, otherwise an
+	 * {@link IllegalStateException} will be thrown.
+	 * <p>
+	 * A target method (e.g. {@link #target(Consumer)}, {@link #target(Dataset)},
+	 * {@link #target(Graph)} or an equivalent subclass method) MUST have been
+	 * called before calling parse(), otherwise an
+	 * {@link IllegalStateException} will be thrown.
+	 * <p>
+	 * It is undefined if this method is thread-safe, however the
+	 * {@link RDFParser} may be reused (e.g. setting a different source)
+	 * as soon as the {@link Future} has been returned from this method.
+	 * <p>
+	 * The RDFParser SHOULD perform the parsing as an asynchronous
+	 * operation, and return the {@link Future} as soon as preliminary checks
+	 * (such as validity of the {@link #source(IRI)} and
+	 * {@link #contentType(RDFSyntax)} settings) have finished. The future
+	 * SHOULD not mark {@link Future#isDone()} before parsing is complete. A
+	 * synchronous implementation MAY be blocking on the <code>parse()</code>
+	 * call and return a Future that is already {@link Future#isDone()}.
+	 * <p>
+	 * The returned {@link Future} contains a {@link ParseResult}. 
+	 * Implementations may subclass this interface to provide any 
+	 * parser details, e.g. list of warnings. <code>null</code> is a
+	 * possible return value if no details are available, but 
+	 * parsing succeeded.
+	 * <p>
+	 * If an exception occurs during parsing, (e.g. {@link IOException} or
+	 * {@link org.apache.commons.rdf.simple.RDFParseException}), 
+	 * it should be indicated as the
+	 * {@link java.util.concurrent.ExecutionException#getCause()} in the
+	 * {@link java.util.concurrent.ExecutionException} thrown on
+	 * {@link Future#get()}.
+	 * 
+	 * @return A Future that will return the populated {@link Graph} when the
+	 *         parsing has finished.
+	 * @throws IOException
+	 *             If an error occurred while starting to read the source (e.g.
+	 *             file not found, unsupported IRI protocol). Note that IO
+	 *             errors during parsing would instead be the
+	 *             {@link java.util.concurrent.ExecutionException#getCause()} of
+	 *             the {@link java.util.concurrent.ExecutionException} thrown on
+	 *             {@link Future#get()}.
+	 * @throws IllegalStateException
+	 *             If the builder is in an invalid state, e.g. a
+	 *             <code>source</code> has not been set.
+	 */
+	Future<? extends ParseResult> parse() throws IOException, IllegalStateException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/api/src/main/java/org/apache/commons/rdf/experimental/package-info.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/experimental/package-info.java b/api/src/main/java/org/apache/commons/rdf/experimental/package-info.java
new file mode 100644
index 0000000..5f24ddc
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/experimental/package-info.java
@@ -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.
+ */
+/**
+ * Experimental Commons RDF features.
+ * <p>
+ * Interfaces/classes in this package should be considered <strong>at
+ * risk</strong>; they might change or be removed in the next minor update of
+ * Commons RDF.
+ * <p>
+ * When class/interface has stabilized, it will move to the
+ * {@link org.apache.commons.rdf.api} package.
+ * <p>
+ * <ul>
+ * <li>{@link RDFParser} - a builder-like interface for parsing RDF to a
+ * {@link org.apache.commons.rdf.api.Graph} or
+ * {@link org.apache.commons.rdf.api.Dataset}.</li>
+ * </ul>
+ */
+package org.apache.commons.rdf.experimental;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/api/src/test/resources/example-rdf/example.jsonld
----------------------------------------------------------------------
diff --git a/api/src/test/resources/example-rdf/example.jsonld b/api/src/test/resources/example-rdf/example.jsonld
new file mode 100644
index 0000000..d6fb670
--- /dev/null
+++ b/api/src/test/resources/example-rdf/example.jsonld
@@ -0,0 +1,25 @@
+{
+  "@graph" : [ {
+    "@id" : "_:b0",
+    "license" : "http://www.apache.org/licenses/LICENSE-2.0",
+    "rights" : {
+      "@language" : "en",
+      "@value" : "Licensed to the Apache Software Foundation (ASF) under one\n or more contributor license agreements. See the NOTICE file\n distributed with this work for additional information\n regarding copyright ownership. The ASF licenses this file\n to you under the Apache License, Version 2.0 (the\n \"License\"); you may not use this file except in compliance\n with the License.  You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n"
+    }
+  }, {
+    "@graph" : [ {
+      "@id" : "_:b0",
+      "license" : "http://example.com/LICENSE"
+    } ],
+    "@id" : "http://example.com"
+  } ],
+  "@context" : {
+    "rights" : {
+      "@id" : "http://purl.org/dc/terms/rights"
+    },
+    "license" : {
+      "@id" : "http://purl.org/dc/terms/license",
+      "@type" : "@id"
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/api/src/test/resources/example-rdf/example.nq
----------------------------------------------------------------------
diff --git a/api/src/test/resources/example-rdf/example.nq b/api/src/test/resources/example-rdf/example.nq
new file mode 100644
index 0000000..9c5e749
--- /dev/null
+++ b/api/src/test/resources/example-rdf/example.nq
@@ -0,0 +1,3 @@
+_:b1 <http://purl.org/dc/terms/license> <http://www.apache.org/licenses/LICENSE-2.0> .
+_:b1 <http://purl.org/dc/terms/rights> "Licensed to the Apache Software Foundation (ASF) under one\n or more contributor license agreements. See the NOTICE file\n distributed with this work for additional information\n regarding copyright ownership. The ASF licenses this file\n to you under the Apache License, Version 2.0 (the\n \"License\"); you may not use this file except in compliance\n with the License.  You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n"@en .
+_:b1 <http://purl.org/dc/terms/license> <http://example.com/LICENSE> <http://example.com> .

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/api/src/test/resources/example-rdf/example.nt
----------------------------------------------------------------------
diff --git a/api/src/test/resources/example-rdf/example.nt b/api/src/test/resources/example-rdf/example.nt
new file mode 100644
index 0000000..53d3f94
--- /dev/null
+++ b/api/src/test/resources/example-rdf/example.nt
@@ -0,0 +1,2 @@
+_:b1 <http://purl.org/dc/terms/license> <http://www.apache.org/licenses/LICENSE-2.0> .
+_:b1 <http://purl.org/dc/terms/rights> "Licensed to the Apache Software Foundation (ASF) under one\n or more contributor license agreements. See the NOTICE file\n distributed with this work for additional information\n regarding copyright ownership. The ASF licenses this file\n to you under the Apache License, Version 2.0 (the\n \"License\"); you may not use this file except in compliance\n with the License.  You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n"@en .

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/api/src/test/resources/example-rdf/example.rdf
----------------------------------------------------------------------
diff --git a/api/src/test/resources/example-rdf/example.rdf b/api/src/test/resources/example-rdf/example.rdf
new file mode 100644
index 0000000..44adfbc
--- /dev/null
+++ b/api/src/test/resources/example-rdf/example.rdf
@@ -0,0 +1,23 @@
+<rdf:RDF
+    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+    xmlns:j.0="http://purl.org/dc/terms/">
+  <rdf:Description>
+    <j.0:rights xml:lang="en">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.
+</j.0:rights>
+    <j.0:license rdf:resource="http://www.apache.org/licenses/LICENSE-2.0"/>
+  </rdf:Description>
+</rdf:RDF>

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/api/src/test/resources/example-rdf/example.trig
----------------------------------------------------------------------
diff --git a/api/src/test/resources/example-rdf/example.trig b/api/src/test/resources/example-rdf/example.trig
new file mode 100644
index 0000000..9d433ce
--- /dev/null
+++ b/api/src/test/resources/example-rdf/example.trig
@@ -0,0 +1,3 @@
+{ _:b0    <http://purl.org/dc/terms/license>  <http://www.apache.org/licenses/LICENSE-2.0> ;
+          <http://purl.org/dc/terms/rights>  "Licensed to the Apache Software Foundation (ASF) under one\n or more contributor license agreements. See the NOTICE file\n distributed with this work for additional information\n regarding copyright ownership. The ASF licenses this file\n to you under the Apache License, Version 2.0 (the\n \"License\"); you may not use this file except in compliance\n with the License.  You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n"@en .
+}

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/api/src/test/resources/example-rdf/example.ttl
----------------------------------------------------------------------
diff --git a/api/src/test/resources/example-rdf/example.ttl b/api/src/test/resources/example-rdf/example.ttl
new file mode 100644
index 0000000..48b97af
--- /dev/null
+++ b/api/src/test/resources/example-rdf/example.ttl
@@ -0,0 +1,2 @@
+_:b0    <http://purl.org/dc/terms/license>  <http://www.apache.org/licenses/LICENSE-2.0> ;
+        <http://purl.org/dc/terms/rights>  "Licensed to the Apache Software Foundation (ASF) under one\n or more contributor license agreements. See the NOTICE file\n distributed with this work for additional information\n regarding copyright ownership. The ASF licenses this file\n to you under the Apache License, Version 2.0 (the\n \"License\"); you may not use this file except in compliance\n with the License.  You may obtain a copy of the License at\n \n http://www.apache.org/licenses/LICENSE-2.0\n \n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n"@en .

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
deleted file mode 100644
index 9e97487..0000000
--- a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
+++ /dev/null
@@ -1,541 +0,0 @@
-/**
- * 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.commons.rdf.simple;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Optional;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.function.Consumer;
-
-import org.apache.commons.rdf.api.Dataset;
-import org.apache.commons.rdf.api.Graph;
-import org.apache.commons.rdf.api.IRI;
-import org.apache.commons.rdf.api.Quad;
-import org.apache.commons.rdf.api.RDFParserBuilder;
-import org.apache.commons.rdf.api.RDFSyntax;
-import org.apache.commons.rdf.api.RDFTermFactory;
-
-/**
- * Abstract RDFParserBuilder
- * <p>
- * This abstract class keeps the builder properties in protected fields like
- * {@link #sourceFile} using {@link Optional}. Some basic checking like
- * {@link #checkIsAbsolute(IRI)} is performed.
- * <p>
- * This class and its subclasses are {@link Cloneable}, immutable and
- * (therefore) thread-safe - each call to option methods like
- * {@link #contentType(String)} or {@link #source(IRI)} will return a cloned,
- * mutated copy.
- * <p>
- * By default, parsing is done by the abstract method
- * {@link #parseSynchronusly()} - which is executed in a cloned snapshot - hence
- * multiple {@link #parse()} calls are thread-safe. The default {@link #parse()}
- * uses a thread pool in {@link #threadGroup} - but implementations can override
- * {@link #parse()} (e.g. because it has its own threading model or use
- * asynchronous remote execution).
- */
-public abstract class AbstractRDFParserBuilder<T extends AbstractRDFParserBuilder<T>> 
-	implements RDFParserBuilder, Cloneable {	
-	
-	public static final ThreadGroup threadGroup = new ThreadGroup("Commons RDF parsers");
-	private static final ExecutorService threadpool = Executors.newCachedThreadPool(r -> new Thread(threadGroup, r));
-
-	// Basically only used for creating IRIs
-	private static RDFTermFactory internalRdfTermFactory = new SimpleRDFTermFactory();
-
-	/**
-	 * Get the set {@link RDFTermFactory}, if any.
-	 */
-	public Optional<RDFTermFactory> getRdfTermFactory() {
-		return rdfTermFactory;
-	}
-
-	/**
-	 * Get the set content-type {@link RDFSyntax}, if any.
-	 * <p>
-	 * If this is {@link Optional#isPresent()}, then 
-	 * {@link #getContentType()} contains the 
-	 * value of {@link RDFSyntax#mediaType}. 
-	 */
-	public Optional<RDFSyntax> getContentTypeSyntax() {
-		return contentTypeSyntax;
-	}
-	
-	/**
-	 * Get the set content-type String, if any.
-	 * <p>
-	 * If this is {@link Optional#isPresent()} and 
-	 * is recognized by {@link RDFSyntax#byMediaType(String)}, then
-	 * the corresponding {@link RDFSyntax} is set on 
-	 * {@link #getContentType()}, otherwise that is
-	 * {@link Optional#empty()}. 
-	 */
-	public final Optional<String> getContentType() {
-		return contentType;
-	}
-
-	/**
-	 * Get the target to consume parsed Quads.
-	 * <p>
-	 * From the call to {@link #parseSynchronusly()}, this
-	 * method is always {@link Optional#isPresent()}.
-	 * 
-	 */	
-	public Consumer<Quad> getTarget() {
-		return target;
-	}
-
-	/**
-	 * Get the target dataset as set by {@link #target(Dataset)}.
-	 * <p>
-	 * The return value is {@link Optional#isPresent()} if and only if
-	 * {@link #target(Dataset)} has been set, meaning that the implementation
-	 * may choose to append parsed quads to the {@link Dataset} directly instead
-	 * of relying on the generated {@link #getTarget()} consumer.
-	 * <p>
-	 * If this value is present, then {@link #getTargetGraph()} MUST 
-	 * be {@link Optional#empty()}.
-	 * 
-	 * @return The target Dataset, or {@link Optional#empty()} if another kind of target has been set.
-	 */
-	public Optional<Dataset> getTargetDataset() {
-		return targetDataset;
-	}
-
-	/**
-	 * Get the target graph as set by {@link #target(Graph)}.
-	 * <p>
-	 * The return value is {@link Optional#isPresent()} if and only if
-	 * {@link #target(Graph)} has been set, meaning that the implementation
-	 * may choose to append parsed triples to the {@link Graph} directly instead
-	 * of relying on the generated {@link #getTarget()} consumer.
-	 * <p>
-	 * If this value is present, then {@link #getTargetDataset()} MUST 
-	 * be {@link Optional#empty()}.
-	 * 
-	 * @return The target Graph, or {@link Optional#empty()} if another kind of target has been set.
-	 */	
-	public Optional<Graph>  getTargetGraph() {
-		return targetGraph;
-	}
-	
-	/**
-	 * Get the set base {@link IRI}, if present.
-	 * <p>
-	 * 
-	 */	
-	public Optional<IRI> getBase() {
-		return base;
-	}
-
-	/**
-	 * Get the set source {@link InputStream}.
-	 * <p>
-	 * If this is {@link Optional#isPresent()}, then 
-	 * {@link #getSourceFile()} and {@link #getSourceIri()}
-	 * are {@link Optional#empty()}.
-	 */
-	public Optional<InputStream> getSourceInputStream() {
-		return sourceInputStream;
-	}
-
-	/**
-	 * Get the set source {@link Path}.
-	 * <p>
-	 * If this is {@link Optional#isPresent()}, then 
-	 * {@link #getSourceInputStream()} and {@link #getSourceIri()}
-	 * are {@link Optional#empty()}.
-	 */	
-	public Optional<Path> getSourceFile() {
-		return sourceFile;
-	}
-
-	/**
-	 * Get the set source {@link Path}.
-	 * <p>
-	 * If this is {@link Optional#isPresent()}, then 
-	 * {@link #getSourceInputStream()} and {@link #getSourceInputStream()()}
-	 * are {@link Optional#empty()}.
-	 */		
-	public Optional<IRI> getSourceIri() {
-		return sourceIri;
-	}
-
-
-	private Optional<RDFTermFactory> rdfTermFactory = Optional.empty();
-	private Optional<RDFSyntax> contentTypeSyntax = Optional.empty();
-	private Optional<String> contentType = Optional.empty();
-	private Optional<IRI> base = Optional.empty();
-	private Optional<InputStream> sourceInputStream = Optional.empty();
-	private Optional<Path> sourceFile = Optional.empty();
-	private Optional<IRI> sourceIri = Optional.empty();
-	private Consumer<Quad> target;
-	private Optional<Dataset> targetDataset;
-	private Optional<Graph> targetGraph;
-
-	@SuppressWarnings("unchecked")
-	@Override
-	public T clone() {
-		try {
-			return (T) super.clone();
-		} catch (CloneNotSupportedException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
-	@SuppressWarnings("unchecked")
-	protected T asT() { 
-		return (T) this;
-	}
-	
-	@Override
-	public T rdfTermFactory(RDFTermFactory rdfTermFactory) {
-		AbstractRDFParserBuilder<T> c = clone();
-		c.rdfTermFactory = Optional.ofNullable(rdfTermFactory);
-		return c.asT();
-	}
-
-	@Override
-	public T contentType(RDFSyntax rdfSyntax) throws IllegalArgumentException {
-		AbstractRDFParserBuilder<T> c = clone();
-		c.contentTypeSyntax = Optional.ofNullable(rdfSyntax);
-		c.contentType = c.contentTypeSyntax.map(syntax -> syntax.mediaType);
-		return c.asT();
-	}
-
-	@Override
-	public T contentType(String contentType) throws IllegalArgumentException {
-		AbstractRDFParserBuilder<T> c = clone();
-		c.contentType = Optional.ofNullable(contentType);
-		c.contentTypeSyntax = c.contentType.flatMap(RDFSyntax::byMediaType);
-		return c.asT();
-	}
-
-	@Override
-	public T base(IRI base) {
-		AbstractRDFParserBuilder<T> c = clone();
-		c.base = Optional.ofNullable(base);
-		c.base.ifPresent(i -> checkIsAbsolute(i));
-		return c.asT();
-	}
-
-	@Override
-	public T base(String base) throws IllegalArgumentException {
-		return base(internalRdfTermFactory.createIRI(base));
-	}
-
-	@Override
-	public T source(InputStream inputStream) {
-		AbstractRDFParserBuilder<T> c = clone();
-		c.resetSource();
-		c.sourceInputStream = Optional.ofNullable(inputStream);
-		return c.asT();
-	}
-
-	@Override
-	public T source(Path file) {
-		AbstractRDFParserBuilder<T> c = clone();
-		c.resetSource();
-		c.sourceFile = Optional.ofNullable(file);
-		return c.asT();
-	}
-
-	@Override
-	public T source(IRI iri) {
-		AbstractRDFParserBuilder<T> c = clone();
-		c.resetSource();
-		c.sourceIri = Optional.ofNullable(iri);
-		c.sourceIri.ifPresent(i -> checkIsAbsolute(i));
-		return c.asT();
-	}
-
-	@Override
-	public T source(String iri) throws IllegalArgumentException {
-		AbstractRDFParserBuilder<T> c = clone();
-		c.resetSource();
-		c.sourceIri = Optional.ofNullable(iri).map(internalRdfTermFactory::createIRI);
-		c.sourceIri.ifPresent(i -> checkIsAbsolute(i));
-		return source(internalRdfTermFactory.createIRI(iri));
-	}
-
-	/**
-	 * Check if an iri is absolute.
-	 * <p>
-	 * Used by {@link #source(String)} and {@link #base(String)}
-	 * 
-	 * @param iri
-	 */
-	protected void checkIsAbsolute(IRI iri) {
-		if (!URI.create(iri.getIRIString()).isAbsolute()) {
-			throw new IllegalArgumentException("IRI is not absolute: " + iri);
-		}
-	}
-
-	/**
-	 * Check that one and only one source is present and valid.
-	 * <p>
-	 * Used by {@link #parse()}.
-	 * <p>
-	 * Subclasses might override this method, e.g. to support other
-	 * source combinations, or to check if the sourceIri is 
-	 * resolvable. 
-	 * 
-	 * @throws IOException If a source file can't be read
-	 */
-	protected void checkSource() throws IOException {
-		if (!sourceFile.isPresent() && !sourceInputStream.isPresent() && !sourceIri.isPresent()) {
-			throw new IllegalStateException("No source has been set");
-		}
-		if (sourceIri.isPresent() && sourceInputStream.isPresent()) {
-			throw new IllegalStateException("Both sourceIri and sourceInputStream have been set");
-		}
-		if (sourceIri.isPresent() && sourceFile.isPresent()) {
-			throw new IllegalStateException("Both sourceIri and sourceFile have been set");
-		}
-		if (sourceInputStream.isPresent() && sourceFile.isPresent()) {
-			throw new IllegalStateException("Both sourceInputStream and sourceFile have been set");
-		}
-		if (sourceFile.isPresent() && !sourceFile.filter(Files::isReadable).isPresent()) {
-			throw new IOException("Can't read file: " + sourceFile);
-		}
-	}
-
-	/**
-	 * Check if base is required.
-	 * 
-	 * @throws IllegalStateException if base is required, but not set.
-	 */
-	protected void checkBaseRequired() {
-		if (!base.isPresent() && sourceInputStream.isPresent()
-				&& !contentTypeSyntax.filter(t -> t == RDFSyntax.NQUADS || t == RDFSyntax.NTRIPLES).isPresent()) {
-			throw new IllegalStateException("base iri required for inputstream source");
-		}
-	}
-
-	/**
-	 * Reset all source* fields to Optional.empty()
-	 * <p>
-	 * Subclasses should override this and call <code>super.resetSource()</code>
-	 * if they need to reset any additional source* fields.
-	 * 
-	 */
-	protected void resetSource() {
-		sourceInputStream = Optional.empty();
-		sourceIri = Optional.empty();
-		sourceFile = Optional.empty();
-	}
-
-
-	/**
-	 * Reset all optional target* fields to Optional.empty()</code>
-	 * <p>
-	 * Note that the consumer set for {@link #getTarget()} is
-	 * NOT reset.
-	 * <p>
-	 * Subclasses should override this and call <code>super.resetTarget()</code>
-	 * if they need to reset any additional target* fields.
-	 * 
-	 */
-	protected void resetTarget() {
-		targetDataset = Optional.empty();
-		targetGraph = Optional.empty();
-	}	
-	
-	/**
-	 * Parse {@link #sourceInputStream}, {@link #sourceFile} or
-	 * {@link #sourceIri}.
-	 * <p>
-	 * One of the source fields MUST be present, as checked by {@link #checkSource()}.
-	 * <p>
-	 * {@link #checkBaseRequired()} is called to verify if {@link #getBase()} is required.
-	 * 
-	 * @throws IOException If the source could not be read 
-	 * @throws RDFParseException If the source could not be parsed (e.g. a .ttl file was not valid Turtle)
-	 */
-	protected abstract void parseSynchronusly() throws IOException, RDFParseException;
-
-	/**
-	 * Prepare a clone of this RDFParserBuilder which have been checked and
-	 * completed.
-	 * <p>
-	 * The returned clone will always have
-	 * {@link #getTarget()} and {@link #getRdfTermFactory()} present.
-	 * <p>
-	 * If the {@link #getSourceFile()} is present, but the 
-	 * {@link #getBase()} is not present, the base will be set to the
-	 * <code>file:///</code> IRI for the Path's real path (e.g. resolving any 
-	 * symbolic links).  
-	 *  
-	 * @return A completed and checked clone of this RDFParserBuilder
-	 * @throws IOException If the source was not accessible (e.g. a file was not found)
-	 * @throws IllegalStateException If the parser was not in a compatible setting (e.g. contentType was an invalid string) 
-	 */
-	protected T prepareForParsing() throws IOException, IllegalStateException {
-		checkSource();
-		checkBaseRequired();		
-		checkContentType();
-		checkTarget();
-
-		// We'll make a clone of our current state which will be passed to
-		// parseSynchronously()
-		AbstractRDFParserBuilder<T> c = clone();
-
-		// Use a fresh SimpleRDFTermFactory for each parse
-		if (!c.rdfTermFactory.isPresent()) {
-			c.rdfTermFactory = Optional.of(createRDFTermFactory());
-		}
-		// sourceFile, but no base? Let's follow any symlinks and use
-		// the file:/// URI
-		if (c.sourceFile.isPresent() && !c.base.isPresent()) {
-			URI baseUri = c.sourceFile.get().toRealPath().toUri();
-			c.base = Optional.of(internalRdfTermFactory.createIRI(baseUri.toString()));
-		}
-
-		return c.asT();
-	}
-	
-	/**
-	 * Subclasses can override this method to check the target is 
-	 * valid.
-	 * <p>
-	 * The default implementation throws an IllegalStateException if the 
-	 * target has not been set.
-	 */
-	protected void checkTarget() {
-		if (target == null) {
-			throw new IllegalStateException("target has not been set");
-		}
-		if (targetGraph.isPresent() && targetDataset.isPresent()) {
-			// This should not happen as each target(..) method resets the optionals
-			throw new IllegalStateException("targetGraph and targetDataset can't both be set");
-		}
-	}
-
-	/**
-	 * Subclasses can override this method to check compatibility with the
-	 * contentType setting.
-	 * 
-	 * @throws IllegalStateException
-	 *             if the {@link #getContentType()} or
-	 *             {@link #getContentTypeSyntax()} is not compatible or invalid
-	 */
-	protected void checkContentType() throws IllegalStateException {
-	}
-
-	/**
-	 * Guess RDFSyntax from a local file's extension.
-	 * <p>
-	 * This method can be used by subclasses if {@link #getContentType()} is not
-	 * present and {@link #getSourceFile()} is set.
-	 * 
-	 * @param path Path which extension should be checked
-	 * @return The {@link RDFSyntax} which has a matching {@link RDFSyntax#fileExtension}, 
-	 * 	otherwise {@link Optional#empty()}. 
-	 */
-	protected static Optional<RDFSyntax> guessRDFSyntax(Path path) {
-			return fileExtension(path).flatMap(RDFSyntax::byFileExtension);
-	}
-
-	/**
-	 * Return the file extension of a Path - if any.
-	 * <p>
-	 * The returned file extension includes the leading <code>.</code>
-	 * <p>
-	 * Note that this only returns the last extension, e.g. the 
-	 * file extension for <code>archive.tar.gz</code> would be <code>.gz</code>
-	 * 
-	 * @param path Path which filename might contain an extension
-	 * @return File extension (including the leading <code>.</code>, 
-	 * 	or {@link Optional#empty()} if the path has no extension
-	 */
-	private static Optional<String> fileExtension(Path path) {
-		Path fileName = path.getFileName();
-		if (fileName == null) { 
-			return Optional.empty();
-		}
-		String filenameStr = fileName.toString();
-		int last = filenameStr.lastIndexOf(".");
-		if (last > -1) { 
-			return Optional.of(filenameStr.substring(last));				
-		}
-		return Optional.empty();
-	}
-	
-
-	/**
-	 * Create a new {@link RDFTermFactory} for a parse session.
-	 * <p>
-	 * This is called by {@link #parse()} to set 
-	 * {@link #rdfTermFactory(RDFTermFactory)} if it is
-	 * {@link Optional#empty()}.
-	 * <p>
-	 * As parsed blank nodes might be made with 
-	 * {@link RDFTermFactory#createBlankNode(String)}, 
-	 * each call to this method SHOULD return 
-	 * a new RDFTermFactory instance.
-	 * 
-	 * @return A new {@link RDFTermFactory}
-	 */
-	protected RDFTermFactory createRDFTermFactory() {
-		return new SimpleRDFTermFactory();
-	}
-
-	@Override
-	public Future<ParseResult> parse() throws IOException, IllegalStateException {
-		final AbstractRDFParserBuilder<T> c = prepareForParsing();
-		return threadpool.submit(() -> {
-			c.parseSynchronusly();
-			return null;
-		});
-	}
-
-	@Override
-	public T target(Consumer<Quad> consumer) {
-		AbstractRDFParserBuilder<T> c = clone();
-		c.resetTarget();
-		c.target = consumer;
-		return c.asT();
-	}
-	
-	@Override
-	public T target(Dataset dataset) {
-		@SuppressWarnings({ "rawtypes", "unchecked" })
-		AbstractRDFParserBuilder<T> c = (AbstractRDFParserBuilder) RDFParserBuilder.super.target(dataset);
-		c.resetTarget();
-		c.targetDataset = Optional.of(dataset);
-		return c.asT();
-	}
-	
-	@Override
-	public T target(Graph graph) {
-		@SuppressWarnings({ "rawtypes", "unchecked" }) // super calls our .clone()
-		AbstractRDFParserBuilder<T> c = (AbstractRDFParserBuilder) RDFParserBuilder.super.target(graph);
-		c.resetTarget();
-		c.targetGraph = Optional.of(graph);
-		return c.asT();
-	}
-	
-
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/simple/src/main/java/org/apache/commons/rdf/simple/RDFParseException.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/RDFParseException.java b/simple/src/main/java/org/apache/commons/rdf/simple/RDFParseException.java
deleted file mode 100644
index ed16bb2..0000000
--- a/simple/src/main/java/org/apache/commons/rdf/simple/RDFParseException.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * 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.commons.rdf.simple;
-
-import org.apache.commons.rdf.api.RDFParserBuilder;
-
-public class RDFParseException extends Exception {
-	private static final long serialVersionUID = 5427752643780702976L;
-	private RDFParserBuilder builder;
-
-	public RDFParseException(RDFParserBuilder builder) {
-		super();
-		this.builder = builder;
-	}
-
-	public RDFParseException(RDFParserBuilder builder, String message, Throwable cause) {
-		super(message, cause);
-		this.builder = builder;
-	}
-
-	public RDFParseException(RDFParserBuilder builder, String message) {
-		super(message);
-		this.builder = builder;
-	}
-
-	public RDFParseException(RDFParserBuilder builder, Throwable cause) {
-		super(cause);
-		this.builder = builder;
-	}
-
-	public RDFParserBuilder getRDFParserBuilder() {
-		return builder;
-	}
-}
\ No newline at end of file


[29/36] incubator-commonsrdf git commit: Merge branch 'master' into parser-with-quads

Posted by st...@apache.org.
Merge branch 'master' into parser-with-quads


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/b1b657f6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/b1b657f6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/b1b657f6

Branch: refs/heads/master
Commit: b1b657f67b2bb3aa65afc32916d6f03b593053bd
Parents: c84a9ea 9782a58
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Fri Sep 9 16:28:11 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Sep 9 16:28:11 2016 +0100

----------------------------------------------------------------------
 LICENSE-header.txt                              |  16 +
 RELEASE-PROCESS.md                              |  20 ++
 api/pom.xml                                     |   5 +-
 .../org/apache/commons/rdf/api/GraphLike.java   |   6 +-
 .../java/org/apache/commons/rdf/api/Quad.java   |   2 +
 .../org/apache/commons/rdf/api/QuadLike.java    |   6 +-
 .../apache/commons/rdf/api/RDFTermFactory.java  |   1 +
 .../java/org/apache/commons/rdf/api/Triple.java |   2 +
 .../org/apache/commons/rdf/api/TripleLike.java  |   6 +-
 api/src/site/resources/profile.jacoco           |   0
 api/src/site/resources/profile.japicmp          |   0
 pom.xml                                         | 307 ++++++++++++-------
 simple/src/site/resources/profile.jacoco        |   0
 simple/src/site/resources/profile.japicmp       |   0
 src/conf/checkstyle-suppressions.xml            |  32 ++
 src/conf/checkstyle.xml                         | 197 ++++++++++++
 src/conf/findbugs-exclude-filter.xml            |  27 ++
 src/conf/pmd.xml                                |  25 ++
 src/site/markdown/implementations.md            |  63 +++-
 src/site/markdown/index.md                      |  58 +++-
 src/site/resources/images/class-diagram.nomnoml |  49 ++-
 src/site/resources/images/class-diagram.png     | Bin 57632 -> 56161 bytes
 src/site/site.xml                               |   3 +-
 23 files changed, 664 insertions(+), 161 deletions(-)
----------------------------------------------------------------------



[30/36] incubator-commonsrdf git commit: Removed unused import

Posted by st...@apache.org.
Removed unused import


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/cbfb670b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/cbfb670b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/cbfb670b

Branch: refs/heads/master
Commit: cbfb670b6f39f5cb4e1ffffcb35746263b9decf4
Parents: b1b657f
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Fri Sep 9 16:40:36 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Sep 9 16:40:36 2016 +0100

----------------------------------------------------------------------
 .../org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java   | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/cbfb670b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
index 4a5b4d1..0dc0e67 100644
--- a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
@@ -33,7 +33,6 @@ import org.apache.commons.rdf.api.Graph;
 import org.apache.commons.rdf.api.IRI;
 import org.apache.commons.rdf.api.Quad;
 import org.apache.commons.rdf.api.RDFParserBuilder;
-import org.apache.commons.rdf.api.RDFParserBuilder.ParseResult;
 import org.apache.commons.rdf.api.RDFSyntax;
 import org.apache.commons.rdf.api.RDFTermFactory;
 
@@ -57,7 +56,7 @@ import org.apache.commons.rdf.api.RDFTermFactory;
  * asynchronous remote execution).
  */
 public abstract class AbstractRDFParserBuilder<T extends AbstractRDFParserBuilder<T>> 
-	implements RDFParserBuilder, Cloneable {
+	implements RDFParserBuilder, Cloneable {	
 	
 	public static final ThreadGroup threadGroup = new ThreadGroup("Commons RDF parsers");
 	private static final ExecutorService threadpool = Executors.newCachedThreadPool(r -> new Thread(threadGroup, r));


[31/36] incubator-commonsrdf git commit: internally map on simple graph.contains()

Posted by st...@apache.org.
internally map on simple graph.contains()

.. so we get consistent BlankNode mapping


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/de7fe8a2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/de7fe8a2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/de7fe8a2

Branch: refs/heads/master
Commit: de7fe8a2bfccc3619c87c7f3903a09f95870ab60
Parents: 9782a58
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Mon Sep 12 19:01:17 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Mon Sep 12 19:01:17 2016 +0100

----------------------------------------------------------------------
 .../apache/commons/rdf/simple/GraphImpl.java    | 39 +++++++++++---------
 1 file changed, 21 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/de7fe8a2/simple/src/main/java/org/apache/commons/rdf/simple/GraphImpl.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/GraphImpl.java b/simple/src/main/java/org/apache/commons/rdf/simple/GraphImpl.java
index 1f19d57..779b1ad 100644
--- a/simple/src/main/java/org/apache/commons/rdf/simple/GraphImpl.java
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/GraphImpl.java
@@ -55,21 +55,7 @@ final class GraphImpl implements Graph {
 
     @Override
     public void add(Triple triple) {
-        BlankNodeOrIRI newSubject = (BlankNodeOrIRI) internallyMap(triple
-                .getSubject());
-        IRI newPredicate = (IRI) internallyMap(triple.getPredicate());
-        RDFTerm newObject = internallyMap(triple.getObject());
-        // Check if any of the object references changed during the mapping, to
-        // avoid creating a new Triple object if possible
-        if (newSubject == triple.getSubject()
-                && newPredicate == triple.getPredicate()
-                && newObject == triple.getObject()) {
-            triples.add(triple);
-        } else {
-            Triple result = factory.createTriple(newSubject, newPredicate,
-                    newObject);
-            triples.add(result);
-        }
+    	triples.add(internallyMap(triple));
     }
 
     private <T extends RDFTerm> RDFTerm internallyMap(T object) {
@@ -103,6 +89,23 @@ final class GraphImpl implements Graph {
         }
     }
 
+    private Triple internallyMap(Triple triple) {
+        BlankNodeOrIRI newSubject = (BlankNodeOrIRI) internallyMap(triple
+                .getSubject());
+        IRI newPredicate = (IRI) internallyMap(triple.getPredicate());
+        RDFTerm newObject = internallyMap(triple.getObject());
+        // Check if any of the object references changed during the mapping, to
+        // avoid creating a new Triple object if possible
+        if (newSubject == triple.getSubject()
+                && newPredicate == triple.getPredicate()
+                && newObject == triple.getObject()) {
+            return triple;
+        } else {
+            return factory.createTriple(newSubject, newPredicate,
+                    newObject);
+        }
+    }
+
     @Override
     public void clear() {
         triples.clear();
@@ -116,10 +119,10 @@ final class GraphImpl implements Graph {
 
     @Override
     public boolean contains(Triple triple) {
-        return triples.contains(Objects.requireNonNull(triple));
+    	return triples.contains(internallyMap(triple));
     }
-
-    @Override
+    
+	@Override
     public Stream<Triple> stream() {
         return triples.parallelStream().unordered();
     }


[03/36] incubator-commonsrdf git commit: javadoc syntax

Posted by st...@apache.org.
javadoc syntax


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/36675922
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/36675922
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/36675922

Branch: refs/heads/master
Commit: 366759224381711c943b4d39590cee214a12d3ee
Parents: 0693671
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Sun Mar 27 20:25:55 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Apr 1 16:19:58 2016 +0100

----------------------------------------------------------------------
 .../java/org/apache/commons/rdf/api/RDFParserBuilder.java   | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/36675922/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index adee4e4..0aacb6a 100644
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -19,10 +19,8 @@ package org.apache.commons.rdf.api;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
-import java.util.Locale;
 import java.util.concurrent.Future;
 
 /**
@@ -126,7 +124,8 @@ public interface RDFParserBuilder {
 	 * <p>
 	 * The default if this option has not been set is that each call to
 	 * {@link #parse()} will return a new {@link Graph} (created using
-	 * {@link RDFTermFactory#createGraph() if #rdfTermFactory(RDFTermFactory)
+	 * {@link RDFTermFactory#createGraph()} 
+	 * if {@link #rdfTermFactory(RDFTermFactory)}
 	 * has been set).
 	 * 
 	 * @param graph
@@ -140,7 +139,7 @@ public interface RDFParserBuilder {
 	 * Specify a base IRI to use for parsing any relative IRI references.
 	 * <p>
 	 * Setting this option will override any protocol-specific base IRI (e.g.
-	 * <code>Content-Location</code> header) or the {@link #source(URL)} URL,
+	 * <code>Content-Location</code> header) or the {@link #source(IRI)} IRI,
 	 * but does not override any base IRIs set within the source document (e.g.
 	 * <code>@base</code> in Turtle documents).
 	 * <p>
@@ -161,7 +160,7 @@ public interface RDFParserBuilder {
 	 * Specify a base IRI to use for parsing any relative IRI references.
 	 * <p>
 	 * Setting this option will override any protocol-specific base IRI (e.g.
-	 * <code>Content-Location</code> header) or the {@link #source(URL)} URL,
+	 * <code>Content-Location</code> header) or the {@link #source(IRI)} IRI,
 	 * but does not override any base IRIs set within the source document (e.g.
 	 * <code>@base</code> in Turtle documents).
 	 * <p>


[16/36] incubator-commonsrdf git commit: javadoc typos

Posted by st...@apache.org.
javadoc typos


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/13a6b07d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/13a6b07d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/13a6b07d

Branch: refs/heads/master
Commit: 13a6b07d864e7a4693139f5f75e85dd66c09b5fd
Parents: df35ebc
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Sun Apr 3 03:12:08 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Sun Apr 3 03:12:08 2016 +0100

----------------------------------------------------------------------
 .../apache/commons/rdf/simple/AbstractRDFParserBuilder.java   | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/13a6b07d/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
index 34aeb5a..2430d26 100644
--- a/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilder.java
@@ -258,9 +258,12 @@ public abstract class AbstractRDFParserBuilder implements RDFParserBuilder, Clon
 	 * Check that one and only one source is present and valid.
 	 * <p>
 	 * Used by {@link #parse()}.
+	 * <p>
+	 * Subclasses might override this method, e.g. to support other
+	 * source combinations, or to check if the sourceIri is 
+	 * resolvable. 
 	 * 
-	 * @param iri
-	 * @throws IOException
+	 * @throws IOException If a source file can't be read
 	 */
 	protected void checkSource() throws IOException {
 		if (!sourceFile.isPresent() && !sourceInputStream.isPresent() && !sourceIri.isPresent()) {


[34/36] incubator-commonsrdf git commit: COMMONSRDF-39 experimental RDFParser interface

Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/simple/src/main/java/org/apache/commons/rdf/simple/experimental/AbstractRDFParser.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/experimental/AbstractRDFParser.java b/simple/src/main/java/org/apache/commons/rdf/simple/experimental/AbstractRDFParser.java
new file mode 100644
index 0000000..8111f09
--- /dev/null
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/experimental/AbstractRDFParser.java
@@ -0,0 +1,542 @@
+/**
+ * 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.commons.rdf.simple.experimental;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Optional;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.function.Consumer;
+
+import org.apache.commons.rdf.api.Dataset;
+import org.apache.commons.rdf.api.Graph;
+import org.apache.commons.rdf.api.IRI;
+import org.apache.commons.rdf.api.Quad;
+import org.apache.commons.rdf.api.RDFSyntax;
+import org.apache.commons.rdf.api.RDFTermFactory;
+import org.apache.commons.rdf.experimental.RDFParser;
+import org.apache.commons.rdf.simple.SimpleRDFTermFactory;
+
+/**
+ * Abstract RDFParser
+ * <p>
+ * This abstract class keeps the properties in protected fields like
+ * {@link #sourceFile} using {@link Optional}. Some basic checking like
+ * {@link #checkIsAbsolute(IRI)} is performed.
+ * <p>
+ * This class and its subclasses are {@link Cloneable}, immutable and
+ * (therefore) thread-safe - each call to option methods like
+ * {@link #contentType(String)} or {@link #source(IRI)} will return a cloned,
+ * mutated copy.
+ * <p>
+ * By default, parsing is done by the abstract method
+ * {@link #parseSynchronusly()} - which is executed in a cloned snapshot - hence
+ * multiple {@link #parse()} calls are thread-safe. The default {@link #parse()}
+ * uses a thread pool in {@link #threadGroup} - but implementations can override
+ * {@link #parse()} (e.g. because it has its own threading model or use
+ * asynchronous remote execution).
+ */
+public abstract class AbstractRDFParser<T extends AbstractRDFParser<T>> 
+	implements RDFParser, Cloneable {	
+	
+	public static final ThreadGroup threadGroup = new ThreadGroup("Commons RDF parsers");
+	private static final ExecutorService threadpool = Executors.newCachedThreadPool(r -> new Thread(threadGroup, r));
+
+	// Basically only used for creating IRIs
+	private static RDFTermFactory internalRdfTermFactory = new SimpleRDFTermFactory();
+
+	/**
+	 * Get the set {@link RDFTermFactory}, if any.
+	 */
+	public Optional<RDFTermFactory> getRdfTermFactory() {
+		return rdfTermFactory;
+	}
+
+	/**
+	 * Get the set content-type {@link RDFSyntax}, if any.
+	 * <p>
+	 * If this is {@link Optional#isPresent()}, then 
+	 * {@link #getContentType()} contains the 
+	 * value of {@link RDFSyntax#mediaType}. 
+	 */
+	public Optional<RDFSyntax> getContentTypeSyntax() {
+		return contentTypeSyntax;
+	}
+	
+	/**
+	 * Get the set content-type String, if any.
+	 * <p>
+	 * If this is {@link Optional#isPresent()} and 
+	 * is recognized by {@link RDFSyntax#byMediaType(String)}, then
+	 * the corresponding {@link RDFSyntax} is set on 
+	 * {@link #getContentType()}, otherwise that is
+	 * {@link Optional#empty()}. 
+	 */
+	public final Optional<String> getContentType() {
+		return contentType;
+	}
+
+	/**
+	 * Get the target to consume parsed Quads.
+	 * <p>
+	 * From the call to {@link #parseSynchronusly()}, this
+	 * method is always {@link Optional#isPresent()}.
+	 * 
+	 */	
+	public Consumer<Quad> getTarget() {
+		return target;
+	}
+
+	/**
+	 * Get the target dataset as set by {@link #target(Dataset)}.
+	 * <p>
+	 * The return value is {@link Optional#isPresent()} if and only if
+	 * {@link #target(Dataset)} has been set, meaning that the implementation
+	 * may choose to append parsed quads to the {@link Dataset} directly instead
+	 * of relying on the generated {@link #getTarget()} consumer.
+	 * <p>
+	 * If this value is present, then {@link #getTargetGraph()} MUST 
+	 * be {@link Optional#empty()}.
+	 * 
+	 * @return The target Dataset, or {@link Optional#empty()} if another kind of target has been set.
+	 */
+	public Optional<Dataset> getTargetDataset() {
+		return targetDataset;
+	}
+
+	/**
+	 * Get the target graph as set by {@link #target(Graph)}.
+	 * <p>
+	 * The return value is {@link Optional#isPresent()} if and only if
+	 * {@link #target(Graph)} has been set, meaning that the implementation
+	 * may choose to append parsed triples to the {@link Graph} directly instead
+	 * of relying on the generated {@link #getTarget()} consumer.
+	 * <p>
+	 * If this value is present, then {@link #getTargetDataset()} MUST 
+	 * be {@link Optional#empty()}.
+	 * 
+	 * @return The target Graph, or {@link Optional#empty()} if another kind of target has been set.
+	 */	
+	public Optional<Graph>  getTargetGraph() {
+		return targetGraph;
+	}
+	
+	/**
+	 * Get the set base {@link IRI}, if present.
+	 * <p>
+	 * 
+	 */	
+	public Optional<IRI> getBase() {
+		return base;
+	}
+
+	/**
+	 * Get the set source {@link InputStream}.
+	 * <p>
+	 * If this is {@link Optional#isPresent()}, then 
+	 * {@link #getSourceFile()} and {@link #getSourceIri()}
+	 * are {@link Optional#empty()}.
+	 */
+	public Optional<InputStream> getSourceInputStream() {
+		return sourceInputStream;
+	}
+
+	/**
+	 * Get the set source {@link Path}.
+	 * <p>
+	 * If this is {@link Optional#isPresent()}, then 
+	 * {@link #getSourceInputStream()} and {@link #getSourceIri()}
+	 * are {@link Optional#empty()}.
+	 */	
+	public Optional<Path> getSourceFile() {
+		return sourceFile;
+	}
+
+	/**
+	 * Get the set source {@link Path}.
+	 * <p>
+	 * If this is {@link Optional#isPresent()}, then 
+	 * {@link #getSourceInputStream()} and {@link #getSourceInputStream()()}
+	 * are {@link Optional#empty()}.
+	 */		
+	public Optional<IRI> getSourceIri() {
+		return sourceIri;
+	}
+
+
+	private Optional<RDFTermFactory> rdfTermFactory = Optional.empty();
+	private Optional<RDFSyntax> contentTypeSyntax = Optional.empty();
+	private Optional<String> contentType = Optional.empty();
+	private Optional<IRI> base = Optional.empty();
+	private Optional<InputStream> sourceInputStream = Optional.empty();
+	private Optional<Path> sourceFile = Optional.empty();
+	private Optional<IRI> sourceIri = Optional.empty();
+	private Consumer<Quad> target;
+	private Optional<Dataset> targetDataset;
+	private Optional<Graph> targetGraph;
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public T clone() {
+		try {
+			return (T) super.clone();
+		} catch (CloneNotSupportedException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	protected T asT() { 
+		return (T) this;
+	}
+	
+	@Override
+	public T rdfTermFactory(RDFTermFactory rdfTermFactory) {
+		AbstractRDFParser<T> c = clone();
+		c.rdfTermFactory = Optional.ofNullable(rdfTermFactory);
+		return c.asT();
+	}
+
+	@Override
+	public T contentType(RDFSyntax rdfSyntax) throws IllegalArgumentException {
+		AbstractRDFParser<T> c = clone();
+		c.contentTypeSyntax = Optional.ofNullable(rdfSyntax);
+		c.contentType = c.contentTypeSyntax.map(syntax -> syntax.mediaType);
+		return c.asT();
+	}
+
+	@Override
+	public T contentType(String contentType) throws IllegalArgumentException {
+		AbstractRDFParser<T> c = clone();
+		c.contentType = Optional.ofNullable(contentType);
+		c.contentTypeSyntax = c.contentType.flatMap(RDFSyntax::byMediaType);
+		return c.asT();
+	}
+
+	@Override
+	public T base(IRI base) {
+		AbstractRDFParser<T> c = clone();
+		c.base = Optional.ofNullable(base);
+		c.base.ifPresent(i -> checkIsAbsolute(i));
+		return c.asT();
+	}
+
+	@Override
+	public T base(String base) throws IllegalArgumentException {
+		return base(internalRdfTermFactory.createIRI(base));
+	}
+
+	@Override
+	public T source(InputStream inputStream) {
+		AbstractRDFParser<T> c = clone();
+		c.resetSource();
+		c.sourceInputStream = Optional.ofNullable(inputStream);
+		return c.asT();
+	}
+
+	@Override
+	public T source(Path file) {
+		AbstractRDFParser<T> c = clone();
+		c.resetSource();
+		c.sourceFile = Optional.ofNullable(file);
+		return c.asT();
+	}
+
+	@Override
+	public T source(IRI iri) {
+		AbstractRDFParser<T> c = clone();
+		c.resetSource();
+		c.sourceIri = Optional.ofNullable(iri);
+		c.sourceIri.ifPresent(i -> checkIsAbsolute(i));
+		return c.asT();
+	}
+
+	@Override
+	public T source(String iri) throws IllegalArgumentException {
+		AbstractRDFParser<T> c = clone();
+		c.resetSource();
+		c.sourceIri = Optional.ofNullable(iri).map(internalRdfTermFactory::createIRI);
+		c.sourceIri.ifPresent(i -> checkIsAbsolute(i));
+		return source(internalRdfTermFactory.createIRI(iri));
+	}
+
+	/**
+	 * Check if an iri is absolute.
+	 * <p>
+	 * Used by {@link #source(String)} and {@link #base(String)}
+	 * 
+	 * @param iri
+	 */
+	protected void checkIsAbsolute(IRI iri) {
+		if (!URI.create(iri.getIRIString()).isAbsolute()) {
+			throw new IllegalArgumentException("IRI is not absolute: " + iri);
+		}
+	}
+
+	/**
+	 * Check that one and only one source is present and valid.
+	 * <p>
+	 * Used by {@link #parse()}.
+	 * <p>
+	 * Subclasses might override this method, e.g. to support other
+	 * source combinations, or to check if the sourceIri is 
+	 * resolvable. 
+	 * 
+	 * @throws IOException If a source file can't be read
+	 */
+	protected void checkSource() throws IOException {
+		if (!sourceFile.isPresent() && !sourceInputStream.isPresent() && !sourceIri.isPresent()) {
+			throw new IllegalStateException("No source has been set");
+		}
+		if (sourceIri.isPresent() && sourceInputStream.isPresent()) {
+			throw new IllegalStateException("Both sourceIri and sourceInputStream have been set");
+		}
+		if (sourceIri.isPresent() && sourceFile.isPresent()) {
+			throw new IllegalStateException("Both sourceIri and sourceFile have been set");
+		}
+		if (sourceInputStream.isPresent() && sourceFile.isPresent()) {
+			throw new IllegalStateException("Both sourceInputStream and sourceFile have been set");
+		}
+		if (sourceFile.isPresent() && !sourceFile.filter(Files::isReadable).isPresent()) {
+			throw new IOException("Can't read file: " + sourceFile);
+		}
+	}
+
+	/**
+	 * Check if base is required.
+	 * 
+	 * @throws IllegalStateException if base is required, but not set.
+	 */
+	protected void checkBaseRequired() {
+		if (!base.isPresent() && sourceInputStream.isPresent()
+				&& !contentTypeSyntax.filter(t -> t == RDFSyntax.NQUADS || t == RDFSyntax.NTRIPLES).isPresent()) {
+			throw new IllegalStateException("base iri required for inputstream source");
+		}
+	}
+
+	/**
+	 * Reset all source* fields to Optional.empty()
+	 * <p>
+	 * Subclasses should override this and call <code>super.resetSource()</code>
+	 * if they need to reset any additional source* fields.
+	 * 
+	 */
+	protected void resetSource() {
+		sourceInputStream = Optional.empty();
+		sourceIri = Optional.empty();
+		sourceFile = Optional.empty();
+	}
+
+
+	/**
+	 * Reset all optional target* fields to Optional.empty()</code>
+	 * <p>
+	 * Note that the consumer set for {@link #getTarget()} is
+	 * NOT reset.
+	 * <p>
+	 * Subclasses should override this and call <code>super.resetTarget()</code>
+	 * if they need to reset any additional target* fields.
+	 * 
+	 */
+	protected void resetTarget() {
+		targetDataset = Optional.empty();
+		targetGraph = Optional.empty();
+	}	
+	
+	/**
+	 * Parse {@link #sourceInputStream}, {@link #sourceFile} or
+	 * {@link #sourceIri}.
+	 * <p>
+	 * One of the source fields MUST be present, as checked by {@link #checkSource()}.
+	 * <p>
+	 * {@link #checkBaseRequired()} is called to verify if {@link #getBase()} is required.
+	 * 
+	 * @throws IOException If the source could not be read 
+	 * @throws RDFParseException If the source could not be parsed (e.g. a .ttl file was not valid Turtle)
+	 */
+	protected abstract void parseSynchronusly() throws IOException, RDFParseException;
+
+	/**
+	 * Prepare a clone of this RDFParser which have been checked and
+	 * completed.
+	 * <p>
+	 * The returned clone will always have
+	 * {@link #getTarget()} and {@link #getRdfTermFactory()} present.
+	 * <p>
+	 * If the {@link #getSourceFile()} is present, but the 
+	 * {@link #getBase()} is not present, the base will be set to the
+	 * <code>file:///</code> IRI for the Path's real path (e.g. resolving any 
+	 * symbolic links).  
+	 *  
+	 * @return A completed and checked clone of this RDFParser
+	 * @throws IOException If the source was not accessible (e.g. a file was not found)
+	 * @throws IllegalStateException If the parser was not in a compatible setting (e.g. contentType was an invalid string) 
+	 */
+	protected T prepareForParsing() throws IOException, IllegalStateException {
+		checkSource();
+		checkBaseRequired();		
+		checkContentType();
+		checkTarget();
+
+		// We'll make a clone of our current state which will be passed to
+		// parseSynchronously()
+		AbstractRDFParser<T> c = clone();
+
+		// Use a fresh SimpleRDFTermFactory for each parse
+		if (!c.rdfTermFactory.isPresent()) {
+			c.rdfTermFactory = Optional.of(createRDFTermFactory());
+		}
+		// sourceFile, but no base? Let's follow any symlinks and use
+		// the file:/// URI
+		if (c.sourceFile.isPresent() && !c.base.isPresent()) {
+			URI baseUri = c.sourceFile.get().toRealPath().toUri();
+			c.base = Optional.of(internalRdfTermFactory.createIRI(baseUri.toString()));
+		}
+
+		return c.asT();
+	}
+	
+	/**
+	 * Subclasses can override this method to check the target is 
+	 * valid.
+	 * <p>
+	 * The default implementation throws an IllegalStateException if the 
+	 * target has not been set.
+	 */
+	protected void checkTarget() {
+		if (target == null) {
+			throw new IllegalStateException("target has not been set");
+		}
+		if (targetGraph.isPresent() && targetDataset.isPresent()) {
+			// This should not happen as each target(..) method resets the optionals
+			throw new IllegalStateException("targetGraph and targetDataset can't both be set");
+		}
+	}
+
+	/**
+	 * Subclasses can override this method to check compatibility with the
+	 * contentType setting.
+	 * 
+	 * @throws IllegalStateException
+	 *             if the {@link #getContentType()} or
+	 *             {@link #getContentTypeSyntax()} is not compatible or invalid
+	 */
+	protected void checkContentType() throws IllegalStateException {
+	}
+
+	/**
+	 * Guess RDFSyntax from a local file's extension.
+	 * <p>
+	 * This method can be used by subclasses if {@link #getContentType()} is not
+	 * present and {@link #getSourceFile()} is set.
+	 * 
+	 * @param path Path which extension should be checked
+	 * @return The {@link RDFSyntax} which has a matching {@link RDFSyntax#fileExtension}, 
+	 * 	otherwise {@link Optional#empty()}. 
+	 */
+	protected static Optional<RDFSyntax> guessRDFSyntax(Path path) {
+			return fileExtension(path).flatMap(RDFSyntax::byFileExtension);
+	}
+
+	/**
+	 * Return the file extension of a Path - if any.
+	 * <p>
+	 * The returned file extension includes the leading <code>.</code>
+	 * <p>
+	 * Note that this only returns the last extension, e.g. the 
+	 * file extension for <code>archive.tar.gz</code> would be <code>.gz</code>
+	 * 
+	 * @param path Path which filename might contain an extension
+	 * @return File extension (including the leading <code>.</code>, 
+	 * 	or {@link Optional#empty()} if the path has no extension
+	 */
+	private static Optional<String> fileExtension(Path path) {
+		Path fileName = path.getFileName();
+		if (fileName == null) { 
+			return Optional.empty();
+		}
+		String filenameStr = fileName.toString();
+		int last = filenameStr.lastIndexOf(".");
+		if (last > -1) { 
+			return Optional.of(filenameStr.substring(last));				
+		}
+		return Optional.empty();
+	}
+	
+
+	/**
+	 * Create a new {@link RDFTermFactory} for a parse session.
+	 * <p>
+	 * This is called by {@link #parse()} to set 
+	 * {@link #rdfTermFactory(RDFTermFactory)} if it is
+	 * {@link Optional#empty()}.
+	 * <p>
+	 * As parsed blank nodes might be made with 
+	 * {@link RDFTermFactory#createBlankNode(String)}, 
+	 * each call to this method SHOULD return 
+	 * a new RDFTermFactory instance.
+	 * 
+	 * @return A new {@link RDFTermFactory}
+	 */
+	protected RDFTermFactory createRDFTermFactory() {
+		return new SimpleRDFTermFactory();
+	}
+
+	@Override
+	public Future<ParseResult> parse() throws IOException, IllegalStateException {
+		final AbstractRDFParser<T> c = prepareForParsing();
+		return threadpool.submit(() -> {
+			c.parseSynchronusly();
+			return null;
+		});
+	}
+
+	@Override
+	public T target(Consumer<Quad> consumer) {
+		AbstractRDFParser<T> c = clone();
+		c.resetTarget();
+		c.target = consumer;
+		return c.asT();
+	}
+	
+	@Override
+	public T target(Dataset dataset) {
+		@SuppressWarnings({ "rawtypes", "unchecked" })
+		AbstractRDFParser<T> c = (AbstractRDFParser) RDFParser.super.target(dataset);
+		c.resetTarget();
+		c.targetDataset = Optional.of(dataset);
+		return c.asT();
+	}
+	
+	@Override
+	public T target(Graph graph) {
+		@SuppressWarnings({ "rawtypes", "unchecked" }) // super calls our .clone()
+		AbstractRDFParser<T> c = (AbstractRDFParser) RDFParser.super.target(graph);
+		c.resetTarget();
+		c.targetGraph = Optional.of(graph);
+		return c.asT();
+	}
+	
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/simple/src/main/java/org/apache/commons/rdf/simple/experimental/RDFParseException.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/experimental/RDFParseException.java b/simple/src/main/java/org/apache/commons/rdf/simple/experimental/RDFParseException.java
new file mode 100644
index 0000000..cb3ad82
--- /dev/null
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/experimental/RDFParseException.java
@@ -0,0 +1,50 @@
+/**
+ * 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.commons.rdf.simple.experimental;
+
+import org.apache.commons.rdf.experimental.RDFParser;
+
+public class RDFParseException extends Exception {
+	private static final long serialVersionUID = 5427752643780702976L;
+	private RDFParser builder;
+
+	public RDFParseException(RDFParser builder) {
+		super();
+		this.builder = builder;
+	}
+
+	public RDFParseException(RDFParser builder, String message, Throwable cause) {
+		super(message, cause);
+		this.builder = builder;
+	}
+
+	public RDFParseException(RDFParser builder, String message) {
+		super(message);
+		this.builder = builder;
+	}
+
+	public RDFParseException(RDFParser builder, Throwable cause) {
+		super(cause);
+		this.builder = builder;
+	}
+
+	public RDFParser getRDFParserBuilder() {
+		return builder;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/simple/src/main/java/org/apache/commons/rdf/simple/experimental/package-info.java
----------------------------------------------------------------------
diff --git a/simple/src/main/java/org/apache/commons/rdf/simple/experimental/package-info.java b/simple/src/main/java/org/apache/commons/rdf/simple/experimental/package-info.java
new file mode 100644
index 0000000..5196f42
--- /dev/null
+++ b/simple/src/main/java/org/apache/commons/rdf/simple/experimental/package-info.java
@@ -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.
+ */
+/**
+ * Experimental Commons RDF Simple implementations.
+ * <p>
+ * Classes in this package should be considered <strong>at
+ * risk</strong>; they might change or be removed in the next minor update of
+ * Commons RDF.
+ * <p>
+ * When a class has stabilized, it will move to the
+ * {@link org.apache.commons.rdf.simple} package.
+ * <p>
+ * <ul>
+ * <li>{@link AbstractRDFParser} - an abstract helper class
+ * for implementations of 
+ * {@link org.apache.commons.rdf.api.experimental.RDFParser}.</li>
+ * </ul>
+ */
+package org.apache.commons.rdf.simple.experimental;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java
----------------------------------------------------------------------
diff --git a/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java b/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java
deleted file mode 100644
index 439bacb..0000000
--- a/simple/src/test/java/org/apache/commons/rdf/simple/AbstractRDFParserBuilderTest.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/**
- * 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.commons.rdf.simple;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.commons.rdf.api.Graph;
-import org.apache.commons.rdf.api.IRI;
-import org.apache.commons.rdf.api.Literal;
-import org.apache.commons.rdf.api.RDFParserBuilder;
-import org.apache.commons.rdf.api.RDFSyntax;
-import org.apache.commons.rdf.api.RDFTerm;
-import org.apache.commons.rdf.api.RDFTermFactory;
-import org.apache.commons.rdf.api.Triple;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-public class AbstractRDFParserBuilderTest {
-
-	private RDFTermFactory factory = new SimpleRDFTermFactory();
-	
-	private DummyRDFParserBuilder dummyParser = new DummyRDFParserBuilder();
-	private Path testNt;
-	private Path testTtl;
-	private Path testXml;
-
-	@Before
-	public void createTempFile() throws IOException {
-		testNt = Files.createTempFile("test", ".nt");
-		testTtl = Files.createTempFile("test", ".ttl");
-		testXml = Files.createTempFile("test", ".xml");
-
-		// No need to populate the files as the dummy parser
-		// doesn't actually read anything
-	}
-
-	@After
-	public void deleteTempFiles() throws IOException {
-		Files.deleteIfExists(testNt);
-		Files.deleteIfExists(testTtl);
-		Files.deleteIfExists(testXml);
-	}
-
-	@Test
-	public void guessRDFSyntax() throws Exception {
-		assertEquals(RDFSyntax.NTRIPLES, AbstractRDFParserBuilder.guessRDFSyntax(testNt).get());
-		assertEquals(RDFSyntax.TURTLE, AbstractRDFParserBuilder.guessRDFSyntax(testTtl).get());
-		assertFalse(AbstractRDFParserBuilder.guessRDFSyntax(testXml).isPresent());
-	}
-
-	private void checkGraph(Graph g) throws Exception {				
-		assertTrue(g.size() > 0);		
-		IRI greeting = factory.createIRI("http://example.com/greeting");	
-		// Should only have parsed once!
-		assertEquals(1, g.getTriples(null, greeting, null).count());
-		Triple triple = g.getTriples(null, greeting, null).findAny().get();
-		assertTrue(triple.getSubject() instanceof IRI);
-		IRI parsing = (IRI) triple.getSubject();
-		assertTrue(parsing.getIRIString().startsWith("urn:uuid:"));
-
-		assertEquals("http://example.com/greeting", triple.getPredicate().getIRIString());
-
-		assertTrue(triple.getObject() instanceof Literal);
-		Literal literal = (Literal) triple.getObject();
-		assertEquals("Hello world", literal.getLexicalForm());
-		assertFalse(literal.getLanguageTag().isPresent());
-		assertEquals(Types.XSD_STRING, literal.getDatatype());
-		
-		// Check uniqueness of properties that are always present
-		assertEquals(1, 
-				g.getTriples(null, factory.createIRI("http://example.com/source"), null).count());
-		
-		// Check optional properties that are unique
-		assertTrue(2 > g.getTriples(null, factory.createIRI("http://example.com/base"), null).count());
-		assertTrue(2 > g.getTriples(null, factory.createIRI("http://example.com/contentType"), null).count());
-		assertTrue(2 > g.getTriples(null, factory.createIRI("http://example.com/contentTypeSyntax"), null).count());
-	}
-	
-	@Test
-	public void parseFile() throws Exception {	
-		Graph g = factory.createGraph();
-		RDFParserBuilder parser = dummyParser.source(testNt).target(g);
-		parser.parse().get(5, TimeUnit.SECONDS);
-		checkGraph(g);
-		// FIXME: this could potentially break if the equivalent of /tmp includes
-		// international characters
-		assertEquals("<" + testNt.toUri().toString() + ">", firstPredicate(g, "source"));
-		// Should be set to the file path
-		assertEquals("<" + testNt.toUri().toString() + ">", firstPredicate(g, "base"));		
-
-		// Should NOT have guessed the content type
-		assertNull(firstPredicate(g, "contentType"));
-		assertNull(firstPredicate(g, "contentTypeSyntax"));
-	}
-
-
-	@Test
-	public void parseNoSource() throws Exception {
-		thrown.expect(IllegalStateException.class);
-		dummyParser.parse();		
-	}
-	
-	@Test
-	public void parseBaseAndContentTypeNoSource() throws Exception {
-		// Can set the other options, even without source()
-		IRI base = dummyParser.createRDFTermFactory().createIRI("http://www.example.org/test.rdf");
-		RDFParserBuilder parser = dummyParser.base(base).contentType(RDFSyntax.RDFXML);
-		thrown.expect(IllegalStateException.class);
-		thrown.expectMessage("No source has been set");
-		// but .parse() should fail
-		parser.parse();		
-	}
-	
-	@Test
-	public void parseFileMissing() throws Exception {
-		Files.delete(testNt);
-		// This should not fail yet
-		RDFParserBuilder parser = dummyParser.source(testNt);
-		// but here:
-		thrown.expect(IOException.class);
-		parser.parse();		
-	}
-
-	
-	@Test
-	public void parseFileContentType() throws Exception {
-		Graph g = factory.createGraph();
-		RDFParserBuilder parser = dummyParser
-				.source(testNt)
-				.contentType(RDFSyntax.NTRIPLES)
-				.target(g);
-		parser.parse().get(5, TimeUnit.SECONDS);
-		checkGraph(g);
-		// FIXME: this could potentially break if the equivalent of /tmp includes
-		// international characters
-		assertEquals("<" + testNt.toUri().toString() + ">", firstPredicate(g, "source"));
-		assertEquals("<" + testNt.toUri().toString() + ">", firstPredicate(g, "base"));		
-		assertEquals("\"NTRIPLES\"", firstPredicate(g, "contentTypeSyntax"));
-		assertEquals("\"application/n-triples\"", firstPredicate(g, "contentType"));
-	}
-
-	private String firstPredicate(Graph g, String pred) {
-		return g.getTriples(null, factory.createIRI("http://example.com/" + pred), null)
-				.map(Triple::getObject).map(RDFTerm::ntriplesString).findAny().orElse(null);
-	}
-
-
-	@Rule
-	public ExpectedException thrown = ExpectedException.none();
-	
-	@Test
-	public void parseInputStreamFailsIfBaseMissing() throws Exception {
-		InputStream inputStream = new ByteArrayInputStream(new byte[0]);
-		// Should not fail at this point
-		RDFParserBuilder parser = dummyParser.source(inputStream);
-		// but here:
-		thrown.expect(IllegalStateException.class);
-		thrown.expectMessage("base iri required for inputstream source");
-		parser.parse();
-	}
-
-	@Test
-	public void parseInputStreamWithBase() throws Exception {
-		InputStream inputStream = new ByteArrayInputStream(new byte[0]);
-		IRI base = dummyParser.createRDFTermFactory().createIRI("http://www.example.org/test.rdf");
-		Graph g = factory.createGraph();
-		RDFParserBuilder parser = dummyParser.source(inputStream).base(base).target(g);		
-		parser.parse().get(5, TimeUnit.SECONDS);
-		checkGraph(g);
-		assertEquals("<http://www.example.org/test.rdf>", firstPredicate(g, "base"));
-		// in our particular debug output, 
-		// bnode source indicates InputStream 
-		assertTrue(firstPredicate(g, "source").startsWith("_:"));
-		assertNull(firstPredicate(g, "contentType"));
-		assertNull(firstPredicate(g, "contentTypeSyntax"));
-	}
-	
-	@Test
-	public void parseInputStreamWithNQuads() throws Exception {
-		InputStream inputStream = new ByteArrayInputStream(new byte[0]);
-		Graph g = factory.createGraph();
-		RDFParserBuilder parser = dummyParser.source(inputStream).contentType(RDFSyntax.NQUADS).target(g);		
-		parser.parse().get(5, TimeUnit.SECONDS);
-		checkGraph(g);
-		assertNull(firstPredicate(g, "base"));
-		// in our particular debug output, 
-		// bnode source indicates InputStream 
-		assertTrue(firstPredicate(g, "source").startsWith("_:"));
-		assertEquals("\"application/n-quads\"", firstPredicate(g, "contentType"));
-		assertEquals("\"NQUADS\"", firstPredicate(g, "contentTypeSyntax"));
-	}	
-
-	@Test
-	public void parseIRI() throws Exception {
-		IRI iri = dummyParser.createRDFTermFactory().createIRI("http://www.example.net/test.ttl");
-		Graph g = factory.createGraph();
-		RDFParserBuilder parser = dummyParser.source(iri).target(g);		
-		parser.parse().get(5, TimeUnit.SECONDS);
-		checkGraph(g);
-		assertEquals("<http://www.example.net/test.ttl>", firstPredicate(g, "source"));
-		// No base - assuming the above IRI is always 
-		// the base would break server-supplied base from 
-		// any HTTP Location redirects and  Content-Location header
-		assertNull(firstPredicate(g, "base"));
-		// ".ttl" in IRI string does not imply any content type
-		assertNull(firstPredicate(g, "contentType"));
-		assertNull(firstPredicate(g, "contentTypeSyntax"));
-		
-	}
-	
-	@Test
-	public void parseIRIBaseContentType() throws Exception {
-		IRI iri = dummyParser.createRDFTermFactory().createIRI("http://www.example.net/test.ttl");
-		Graph g = factory.createGraph();
-		RDFParserBuilder parser = dummyParser.source(iri).base(iri).contentType(RDFSyntax.TURTLE).target(g);
-		parser.parse().get(5, TimeUnit.SECONDS);
-		checkGraph(g);
-		assertEquals("<http://www.example.net/test.ttl>", firstPredicate(g, "source"));
-		assertEquals("<http://www.example.net/test.ttl>", firstPredicate(g, "base"));
-		assertEquals("\"TURTLE\"", firstPredicate(g, "contentTypeSyntax"));
-		assertEquals("\"text/turtle\"", firstPredicate(g, "contentType"));
-	}
-
-	
-}

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java b/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
index baf9768..683ef7b 100644
--- a/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
+++ b/simple/src/test/java/org/apache/commons/rdf/simple/DummyRDFParserBuilder.java
@@ -23,18 +23,20 @@ import java.util.function.Consumer;
 
 import org.apache.commons.rdf.api.IRI;
 import org.apache.commons.rdf.api.Quad;
-import org.apache.commons.rdf.api.RDFParserBuilder;
 import org.apache.commons.rdf.api.RDFTermFactory;
+import org.apache.commons.rdf.experimental.RDFParser;
+import org.apache.commons.rdf.simple.experimental.AbstractRDFParser;
+import org.apache.commons.rdf.simple.experimental.RDFParseException;
 
 /** 
- * For test purposes - a {@link RDFParserBuilder} that inserts information
+ * For test purposes - a {@link RDFParser} that inserts information
  * about what it has been asked to parse instead of actually parsing anything.
  * <p>
  * This always insert at least the triple equivalent to:
  * <pre>
  *    <urn:uuid:b7ac3fcc-4d86-4d28-8358-a1cd094974a6> <http://example.com/greeting> "Hello world" .
  * </pre>
- * Additional triples match the corresponding getter in AbstractRDFParserBuilder,
+ * Additional triples match the corresponding getter in AbstractRDFParser,
  * e.g.:
  * <pre>
  *   <urn:uuid:b7ac3fcc-4d86-4d28-8358-a1cd094974a6> <http://example.com/base> <http://www.example.org/> .
@@ -43,7 +45,7 @@ import org.apache.commons.rdf.api.RDFTermFactory;
  * 
  *
  */
-public class DummyRDFParserBuilder extends AbstractRDFParserBuilder<DummyRDFParserBuilder> {
+public class DummyRDFParserBuilder extends AbstractRDFParser<DummyRDFParserBuilder> {
 	
 	@Override
 	protected void parseSynchronusly() throws IOException, IllegalStateException, RDFParseException {		
@@ -57,7 +59,7 @@ public class DummyRDFParserBuilder extends AbstractRDFParserBuilder<DummyRDFPars
 		t.accept(factory.createQuad(null, parsing, factory.createIRI("http://example.com/greeting"), 
 				factory.createLiteral("Hello world")));
 		
-		// Now we'll expose the finalized AbstractRDFParserBuilder settings
+		// Now we'll expose the finalized AbstractRDFParser settings
 		// so they can be inspected by the junit test
 
 		if (getSourceIri().isPresent()) {

http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/10d27cde/simple/src/test/java/org/apache/commons/rdf/simple/experimental/AbstractRDFParserTest.java
----------------------------------------------------------------------
diff --git a/simple/src/test/java/org/apache/commons/rdf/simple/experimental/AbstractRDFParserTest.java b/simple/src/test/java/org/apache/commons/rdf/simple/experimental/AbstractRDFParserTest.java
new file mode 100644
index 0000000..f263029
--- /dev/null
+++ b/simple/src/test/java/org/apache/commons/rdf/simple/experimental/AbstractRDFParserTest.java
@@ -0,0 +1,256 @@
+/**
+ * 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.commons.rdf.simple.experimental;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.rdf.api.Graph;
+import org.apache.commons.rdf.api.IRI;
+import org.apache.commons.rdf.api.Literal;
+import org.apache.commons.rdf.api.RDFSyntax;
+import org.apache.commons.rdf.api.RDFTerm;
+import org.apache.commons.rdf.api.RDFTermFactory;
+import org.apache.commons.rdf.api.Triple;
+import org.apache.commons.rdf.experimental.RDFParser;
+import org.apache.commons.rdf.simple.DummyRDFParserBuilder;
+import org.apache.commons.rdf.simple.SimpleRDFTermFactory;
+import org.apache.commons.rdf.simple.Types;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class AbstractRDFParserTest {
+
+	private RDFTermFactory factory = new SimpleRDFTermFactory();
+	
+	private DummyRDFParserBuilder dummyParser = new DummyRDFParserBuilder();
+	private Path testNt;
+	private Path testTtl;
+	private Path testXml;
+
+	@Before
+	public void createTempFile() throws IOException {
+		testNt = Files.createTempFile("test", ".nt");
+		testTtl = Files.createTempFile("test", ".ttl");
+		testXml = Files.createTempFile("test", ".xml");
+
+		// No need to populate the files as the dummy parser
+		// doesn't actually read anything
+	}
+
+	@After
+	public void deleteTempFiles() throws IOException {
+		Files.deleteIfExists(testNt);
+		Files.deleteIfExists(testTtl);
+		Files.deleteIfExists(testXml);
+	}
+
+	@Test
+	public void guessRDFSyntax() throws Exception {
+		assertEquals(RDFSyntax.NTRIPLES, AbstractRDFParser.guessRDFSyntax(testNt).get());
+		assertEquals(RDFSyntax.TURTLE, AbstractRDFParser.guessRDFSyntax(testTtl).get());
+		assertFalse(AbstractRDFParser.guessRDFSyntax(testXml).isPresent());
+	}
+
+	private void checkGraph(Graph g) throws Exception {				
+		assertTrue(g.size() > 0);		
+		IRI greeting = factory.createIRI("http://example.com/greeting");	
+		// Should only have parsed once!
+		assertEquals(1, g.getTriples(null, greeting, null).count());
+		Triple triple = g.getTriples(null, greeting, null).findAny().get();
+		assertTrue(triple.getSubject() instanceof IRI);
+		IRI parsing = (IRI) triple.getSubject();
+		assertTrue(parsing.getIRIString().startsWith("urn:uuid:"));
+
+		assertEquals("http://example.com/greeting", triple.getPredicate().getIRIString());
+
+		assertTrue(triple.getObject() instanceof Literal);
+		Literal literal = (Literal) triple.getObject();
+		assertEquals("Hello world", literal.getLexicalForm());
+		assertFalse(literal.getLanguageTag().isPresent());
+		assertEquals(Types.XSD_STRING, literal.getDatatype());
+		
+		// Check uniqueness of properties that are always present
+		assertEquals(1, 
+				g.getTriples(null, factory.createIRI("http://example.com/source"), null).count());
+		
+		// Check optional properties that are unique
+		assertTrue(2 > g.getTriples(null, factory.createIRI("http://example.com/base"), null).count());
+		assertTrue(2 > g.getTriples(null, factory.createIRI("http://example.com/contentType"), null).count());
+		assertTrue(2 > g.getTriples(null, factory.createIRI("http://example.com/contentTypeSyntax"), null).count());
+	}
+	
+	@Test
+	public void parseFile() throws Exception {	
+		Graph g = factory.createGraph();
+		RDFParser parser = dummyParser.source(testNt).target(g);
+		parser.parse().get(5, TimeUnit.SECONDS);
+		checkGraph(g);
+		// FIXME: this could potentially break if the equivalent of /tmp includes
+		// international characters
+		assertEquals("<" + testNt.toUri().toString() + ">", firstPredicate(g, "source"));
+		// Should be set to the file path
+		assertEquals("<" + testNt.toUri().toString() + ">", firstPredicate(g, "base"));		
+
+		// Should NOT have guessed the content type
+		assertNull(firstPredicate(g, "contentType"));
+		assertNull(firstPredicate(g, "contentTypeSyntax"));
+	}
+
+
+	@Test
+	public void parseNoSource() throws Exception {
+		thrown.expect(IllegalStateException.class);
+		dummyParser.parse();		
+	}
+	
+	@Test
+	public void parseBaseAndContentTypeNoSource() throws Exception {
+		// Can set the other options, even without source()
+		IRI base = dummyParser.createRDFTermFactory().createIRI("http://www.example.org/test.rdf");
+		RDFParser parser = dummyParser.base(base).contentType(RDFSyntax.RDFXML);
+		thrown.expect(IllegalStateException.class);
+		thrown.expectMessage("No source has been set");
+		// but .parse() should fail
+		parser.parse();		
+	}
+	
+	@Test
+	public void parseFileMissing() throws Exception {
+		Files.delete(testNt);
+		// This should not fail yet
+		RDFParser parser = dummyParser.source(testNt);
+		// but here:
+		thrown.expect(IOException.class);
+		parser.parse();		
+	}
+
+	
+	@Test
+	public void parseFileContentType() throws Exception {
+		Graph g = factory.createGraph();
+		RDFParser parser = dummyParser
+				.source(testNt)
+				.contentType(RDFSyntax.NTRIPLES)
+				.target(g);
+		parser.parse().get(5, TimeUnit.SECONDS);
+		checkGraph(g);
+		// FIXME: this could potentially break if the equivalent of /tmp includes
+		// international characters
+		assertEquals("<" + testNt.toUri().toString() + ">", firstPredicate(g, "source"));
+		assertEquals("<" + testNt.toUri().toString() + ">", firstPredicate(g, "base"));		
+		assertEquals("\"NTRIPLES\"", firstPredicate(g, "contentTypeSyntax"));
+		assertEquals("\"application/n-triples\"", firstPredicate(g, "contentType"));
+	}
+
+	private String firstPredicate(Graph g, String pred) {
+		return g.getTriples(null, factory.createIRI("http://example.com/" + pred), null)
+				.map(Triple::getObject).map(RDFTerm::ntriplesString).findAny().orElse(null);
+	}
+
+
+	@Rule
+	public ExpectedException thrown = ExpectedException.none();
+	
+	@Test
+	public void parseInputStreamFailsIfBaseMissing() throws Exception {
+		InputStream inputStream = new ByteArrayInputStream(new byte[0]);
+		// Should not fail at this point
+		RDFParser parser = dummyParser.source(inputStream);
+		// but here:
+		thrown.expect(IllegalStateException.class);
+		thrown.expectMessage("base iri required for inputstream source");
+		parser.parse();
+	}
+
+	@Test
+	public void parseInputStreamWithBase() throws Exception {
+		InputStream inputStream = new ByteArrayInputStream(new byte[0]);
+		IRI base = dummyParser.createRDFTermFactory().createIRI("http://www.example.org/test.rdf");
+		Graph g = factory.createGraph();
+		RDFParser parser = dummyParser.source(inputStream).base(base).target(g);		
+		parser.parse().get(5, TimeUnit.SECONDS);
+		checkGraph(g);
+		assertEquals("<http://www.example.org/test.rdf>", firstPredicate(g, "base"));
+		// in our particular debug output, 
+		// bnode source indicates InputStream 
+		assertTrue(firstPredicate(g, "source").startsWith("_:"));
+		assertNull(firstPredicate(g, "contentType"));
+		assertNull(firstPredicate(g, "contentTypeSyntax"));
+	}
+	
+	@Test
+	public void parseInputStreamWithNQuads() throws Exception {
+		InputStream inputStream = new ByteArrayInputStream(new byte[0]);
+		Graph g = factory.createGraph();
+		RDFParser parser = dummyParser.source(inputStream).contentType(RDFSyntax.NQUADS).target(g);		
+		parser.parse().get(5, TimeUnit.SECONDS);
+		checkGraph(g);
+		assertNull(firstPredicate(g, "base"));
+		// in our particular debug output, 
+		// bnode source indicates InputStream 
+		assertTrue(firstPredicate(g, "source").startsWith("_:"));
+		assertEquals("\"application/n-quads\"", firstPredicate(g, "contentType"));
+		assertEquals("\"NQUADS\"", firstPredicate(g, "contentTypeSyntax"));
+	}	
+
+	@Test
+	public void parseIRI() throws Exception {
+		IRI iri = dummyParser.createRDFTermFactory().createIRI("http://www.example.net/test.ttl");
+		Graph g = factory.createGraph();
+		RDFParser parser = dummyParser.source(iri).target(g);		
+		parser.parse().get(5, TimeUnit.SECONDS);
+		checkGraph(g);
+		assertEquals("<http://www.example.net/test.ttl>", firstPredicate(g, "source"));
+		// No base - assuming the above IRI is always 
+		// the base would break server-supplied base from 
+		// any HTTP Location redirects and  Content-Location header
+		assertNull(firstPredicate(g, "base"));
+		// ".ttl" in IRI string does not imply any content type
+		assertNull(firstPredicate(g, "contentType"));
+		assertNull(firstPredicate(g, "contentTypeSyntax"));
+		
+	}
+	
+	@Test
+	public void parseIRIBaseContentType() throws Exception {
+		IRI iri = dummyParser.createRDFTermFactory().createIRI("http://www.example.net/test.ttl");
+		Graph g = factory.createGraph();
+		RDFParser parser = dummyParser.source(iri).base(iri).contentType(RDFSyntax.TURTLE).target(g);
+		parser.parse().get(5, TimeUnit.SECONDS);
+		checkGraph(g);
+		assertEquals("<http://www.example.net/test.ttl>", firstPredicate(g, "source"));
+		assertEquals("<http://www.example.net/test.ttl>", firstPredicate(g, "base"));
+		assertEquals("\"TURTLE\"", firstPredicate(g, "contentTypeSyntax"));
+		assertEquals("\"text/turtle\"", firstPredicate(g, "contentType"));
+	}
+
+	
+}



[05/36] incubator-commonsrdf git commit: RDFParserBuilder

Posted by st...@apache.org.
RDFParserBuilder


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/5993d932
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/5993d932
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/5993d932

Branch: refs/heads/master
Commit: 5993d9323c3db1946b9115eeca7fbe2d62435f86
Parents: 35b6b53
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Sun Mar 27 19:39:57 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Apr 1 16:19:58 2016 +0100

----------------------------------------------------------------------
 .../commons/rdf/api/RDFParserBuilder.java       | 198 +++++++++++++++++++
 1 file changed, 198 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/5993d932/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
new file mode 100644
index 0000000..3cd7c94
--- /dev/null
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -0,0 +1,198 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.rdf.api;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.Path;
+
+/**
+ * Builder for parsing an RDF source into a Graph.
+ * <p>
+ * This interface follows the
+ * <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder pattern</a>,
+ * allowing to set parser settings like {@link #contentType(RDFSyntax)} and
+ * {@link #base(IRI)}. A caller MUST at least call one of the
+ * <code>source</code> methods before calling {@link #parse()} on the returned
+ * RDFParserBuilder.
+ * <p>
+ * It is undefined if a RDFParserBuilder is mutable or thread-safe, callers
+ * should always use the returned modified RDFParserBuilder from the builder
+ * methods. The builder may return its own mutated instance, or a cloned builder
+ * with the modified setting.
+ * <p>
+ * Example usage:
+ * </p>
+ * 
+ * <pre>
+ *   Graph g1 = ExampleRDFParserBuilder.source("http://example.com/graph.rdf").parse();
+ *   ExampleRDFParserBuilder.source(Paths.get("/tmp/graph.ttl").contentType(RDFSyntax.TURTLE).intoGraph(g1).parse();
+ * </pre>
+ * 
+ *
+ */
+public interface RDFParserBuilder {
+
+	/**
+	 * Specify which {@link RDFTermFactory} to use for generating
+	 * {@link RDFTerm}s.
+	 * <p>
+	 * This option may be used together with {@link #intoGraph(Graph)} to
+	 * override the implementation's default factory and graph.
+	 * 
+	 * @see #intoGraph(Graph)
+	 * @param rdfTermFactory
+	 *            {@link RDFTermFactory} to use for generating RDFTerms.
+	 * @return An {@link RDFParserBuilder} that will use the specified
+	 *         rdfTermFactory
+	 */
+	RDFParserBuilder rdfTermFactory(RDFTermFactory rdfTermFactory);
+
+	/**
+	 * Specify the content type of the RDF syntax to parse.
+	 * <p>
+	 * This option can be used to select the RDFSyntax of the source, overriding
+	 * any <code>Content-Type</code> headers or equivalent.
+	 * <p>
+	 * If the content type is a 
+	 * <p>
+	 * This method will override any contentType set with
+	 * {@link #contentType(String)}.
+	 * 
+	 * @see #contentType(String)
+	 * @param rdfSyntax
+	 *            An {@link RDFSyntax} to parse the source according to, e.g.
+	 *            {@link RDFSyntax#TURTLE}.
+	 * @throws IllegalArgumentException
+	 *             If this RDFParserBuilder does not support the specified
+	 *             RDFSyntax.
+	 * @return An {@link RDFParserBuilder} that will use the specified content
+	 *         type.
+	 */
+	RDFParserBuilder contentType(RDFSyntax rdfSyntax) throws IllegalArgumentException;
+
+	/**
+	 * Specify the content type of the RDF syntax to parse.
+	 * <p>
+	 * This option can be used to select the RDFSyntax of the source, overriding
+	 * any <code>Content-Type</code> headers or equivalent.
+	 * <p>
+	 * This method will override any contentType set with
+	 * {@link #contentType(RDFSyntax)}.
+	 * 
+	 * @see #contentType(RDFSyntax)
+	 * @param contentType
+	 *            A content-type string, e.g. <code>text/turtle</code>
+	 * @throws IllegalArgumentException
+	 *             If this RDFParserBuilder does not support the specified
+	 *             content-type, or it has an invalid syntax.
+	 * @return An {@link RDFParserBuilder} that will use the specified content
+	 *         type.
+	 */
+	RDFParserBuilder contentType(String contentType);
+
+	/**
+	 * Specify which {@link Graph} to add triples into.
+	 * <p>
+	 * The default if this option has not been set is that 
+	 * each call to {@link #parse()} will return a new {@link Graph} (created using
+	 * {@link RDFTermFactory#createGraph() if #rdfTermFactory(RDFTermFactory)
+	 * has been set).
+	 * 
+	 * @param graph The {@link Graph} to add triples into.
+	 * @return An {@link RDFParserBuilder} that will insert triples into the specified graph.
+	 */
+	RDFParserBuilder intoGraph(Graph graph);
+
+	/**
+	 * Specify a base IRI to use for parsing any relative IRI references.
+	 * <p>
+	 * Setting this option will override any protocol-specific base IRI 
+	 * (e.g. <code>Content-Location</code> header) or the {@link #source(URL)} URL, 
+	 * but does not override any base IRIs set within the source document
+	 * (e.g. <code>@base</code> in Turtle documents).
+	 * <p>
+	 * If the source is in a syntax that does not support relative IRI references, 
+	 * e.g. {@link RDFSyntax#NTRIPLES}, setting the base has no effect.
+	 * <p>
+	 * This method will override any base IRI set with {@link #base(String)}.
+	 *
+	 * @see #base(String)
+	 * @param base An absolute IRI to use as a base
+	 * @return An {@link RDFParserBuilder} that will use the specified base IRI
+	 */
+	RDFParserBuilder base(IRI base);
+
+	/**
+	 * Specify a base IRI to use for parsing any relative IRI references.
+	 * <p>
+	 * Setting this option will override any protocol-specific base IRI 
+	 * (e.g. <code>Content-Location</code> header) or the {@link #source(URL)} URL, 
+	 * but does not override any base IRIs set within the source document
+	 * (e.g. <code>@base</code> in Turtle documents).
+	 * <p>
+	 * If the source is in a syntax that does not support relative IRI references, 
+	 * e.g. {@link RDFSyntax#NTRIPLES}, setting the base has no effect.
+	 * <p>
+	 * This method will override any base IRI set with {@link #base(IRI)}.
+	 *
+	 * @see #base(IRI)
+	 * @param base An absolute IRI to use as a base
+	 * @return An {@link RDFParserBuilder} that will use the specified base IRI
+	 */	
+	RDFParserBuilder base(String base);
+
+	/**
+	 * Specify a source to parse.
+	 * <p>
+	 * The source set will not be accessed before the call to {@link #parse()}. 
+	 * <p>
+	 * The InputStream will not be closed after parsing. The
+	 * InputStream does not need to support {@link InputStream#markSupported()}.
+	 * <p>
+	 * The {@link #contentType(RDFSyntax)} SHOULD be set unless the implementation
+	 * supports syntax guessing.
+	 * <p> 
+	 * The {@link #base(IRI)} MUST be set unless the syntax does not permit relative IRIs
+	 * (e.g.  {@link RDFSyntax#NTRIPLES}).
+	 * 
+	 * @param inputStream
+	 * @return
+	 */
+	RDFParserBuilder source(InputStream inputStream);
+
+	RDFParserBuilder source(Path file);
+
+	RDFParserBuilder source(IRI iri);
+
+	RDFParserBuilder source(String iri);
+
+	/**
+	 * Parse the specified source.
+	 * 
+	 * @return The graph containing (at least) the parsed triples.
+	 * 
+	 * @throws IOException
+	 *             If an error occurred while reading the source.
+	 * @throws IllegalStateException
+	 *             If the builder is in an invalid state, e.g. a
+	 *             <code>source</code> has not been set.
+	 */
+	Graph parse() throws IOException, IllegalStateException;
+}


[04/36] incubator-commonsrdf git commit: charset fun

Posted by st...@apache.org.
charset fun


Project: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/commit/06936715
Tree: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/tree/06936715
Diff: http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/diff/06936715

Branch: refs/heads/master
Commit: 0693671569bcfec02ec616fb6d88901da7c602a3
Parents: 5993d93
Author: Stian Soiland-Reyes <st...@apache.org>
Authored: Sun Mar 27 20:11:00 2016 +0100
Committer: Stian Soiland-Reyes <st...@apache.org>
Committed: Fri Apr 1 16:19:58 2016 +0100

----------------------------------------------------------------------
 .../commons/rdf/api/RDFParserBuilder.java       | 101 ++++++++++++-------
 1 file changed, 66 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-commonsrdf/blob/06936715/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
index 3cd7c94..adee4e4 100644
--- a/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
+++ b/api/src/main/java/org/apache/commons/rdf/api/RDFParserBuilder.java
@@ -20,7 +20,10 @@ package org.apache.commons.rdf.api;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
+import java.util.Locale;
+import java.util.concurrent.Future;
 
 /**
  * Builder for parsing an RDF source into a Graph.
@@ -32,10 +35,10 @@ import java.nio.file.Path;
  * <code>source</code> methods before calling {@link #parse()} on the returned
  * RDFParserBuilder.
  * <p>
- * It is undefined if a RDFParserBuilder is mutable or thread-safe, callers
+ * It is undefined if a RDFParserBuilder is mutable or thread-safe, so callers
  * should always use the returned modified RDFParserBuilder from the builder
- * methods. The builder may return its own mutated instance, or a cloned builder
- * with the modified setting.
+ * methods. The builder may return itself, or a cloned builder with the modified
+ * settings applied.
  * <p>
  * Example usage:
  * </p>
@@ -70,7 +73,10 @@ public interface RDFParserBuilder {
 	 * This option can be used to select the RDFSyntax of the source, overriding
 	 * any <code>Content-Type</code> headers or equivalent.
 	 * <p>
-	 * If the content type is a 
+	 * The character set of the RDFSyntax is assumed to be
+	 * {@link StandardCharsets#UTF_8} unless overridden within the document
+	 * (e.g. <?xml version="1.0" encoding="iso-8859-1"?></code> in
+	 * {@link RDFSyntax#RDFXML}).
 	 * <p>
 	 * This method will override any contentType set with
 	 * {@link #contentType(String)}.
@@ -93,12 +99,20 @@ public interface RDFParserBuilder {
 	 * This option can be used to select the RDFSyntax of the source, overriding
 	 * any <code>Content-Type</code> headers or equivalent.
 	 * <p>
+	 * The content type MAY include a <code>charset</code> parameter if the RDF
+	 * media types which permit it; if <code>charset</code> is not specified the
+	 * default is {@link StandardCharsets#UTF_8} unless overridden within the
+	 * document.
+	 * <p>
 	 * This method will override any contentType set with
 	 * {@link #contentType(RDFSyntax)}.
 	 * 
 	 * @see #contentType(RDFSyntax)
 	 * @param contentType
-	 *            A content-type string, e.g. <code>text/turtle</code>
+	 *            A content-type string, e.g. <code>application/ld+json</code>
+	 *            or <code>text/turtle;charset="UTF-8"</code> as specified by
+	 *            <a href="https://tools.ietf.org/html/rfc7231#section-3.1.1.1">
+	 *            RFC7231</a>.
 	 * @throws IllegalArgumentException
 	 *             If this RDFParserBuilder does not support the specified
 	 *             content-type, or it has an invalid syntax.
@@ -110,31 +124,35 @@ public interface RDFParserBuilder {
 	/**
 	 * Specify which {@link Graph} to add triples into.
 	 * <p>
-	 * The default if this option has not been set is that 
-	 * each call to {@link #parse()} will return a new {@link Graph} (created using
+	 * The default if this option has not been set is that each call to
+	 * {@link #parse()} will return a new {@link Graph} (created using
 	 * {@link RDFTermFactory#createGraph() if #rdfTermFactory(RDFTermFactory)
 	 * has been set).
 	 * 
-	 * @param graph The {@link Graph} to add triples into.
-	 * @return An {@link RDFParserBuilder} that will insert triples into the specified graph.
+	 * @param graph
+	 *            The {@link Graph} to add triples into.
+	 * @return An {@link RDFParserBuilder} that will insert triples into the
+	 *         specified graph.
 	 */
 	RDFParserBuilder intoGraph(Graph graph);
 
 	/**
 	 * Specify a base IRI to use for parsing any relative IRI references.
 	 * <p>
-	 * Setting this option will override any protocol-specific base IRI 
-	 * (e.g. <code>Content-Location</code> header) or the {@link #source(URL)} URL, 
-	 * but does not override any base IRIs set within the source document
-	 * (e.g. <code>@base</code> in Turtle documents).
+	 * Setting this option will override any protocol-specific base IRI (e.g.
+	 * <code>Content-Location</code> header) or the {@link #source(URL)} URL,
+	 * but does not override any base IRIs set within the source document (e.g.
+	 * <code>@base</code> in Turtle documents).
 	 * <p>
-	 * If the source is in a syntax that does not support relative IRI references, 
-	 * e.g. {@link RDFSyntax#NTRIPLES}, setting the base has no effect.
+	 * If the source is in a syntax that does not support relative IRI
+	 * references, e.g. {@link RDFSyntax#NTRIPLES}, setting the base has no
+	 * effect.
 	 * <p>
 	 * This method will override any base IRI set with {@link #base(String)}.
 	 *
 	 * @see #base(String)
-	 * @param base An absolute IRI to use as a base
+	 * @param base
+	 *            An absolute IRI to use as a base
 	 * @return An {@link RDFParserBuilder} that will use the specified base IRI
 	 */
 	RDFParserBuilder base(IRI base);
@@ -142,38 +160,50 @@ public interface RDFParserBuilder {
 	/**
 	 * Specify a base IRI to use for parsing any relative IRI references.
 	 * <p>
-	 * Setting this option will override any protocol-specific base IRI 
-	 * (e.g. <code>Content-Location</code> header) or the {@link #source(URL)} URL, 
-	 * but does not override any base IRIs set within the source document
-	 * (e.g. <code>@base</code> in Turtle documents).
+	 * Setting this option will override any protocol-specific base IRI (e.g.
+	 * <code>Content-Location</code> header) or the {@link #source(URL)} URL,
+	 * but does not override any base IRIs set within the source document (e.g.
+	 * <code>@base</code> in Turtle documents).
 	 * <p>
-	 * If the source is in a syntax that does not support relative IRI references, 
-	 * e.g. {@link RDFSyntax#NTRIPLES}, setting the base has no effect.
+	 * If the source is in a syntax that does not support relative IRI
+	 * references, e.g. {@link RDFSyntax#NTRIPLES}, setting the base has no
+	 * effect.
 	 * <p>
 	 * This method will override any base IRI set with {@link #base(IRI)}.
 	 *
 	 * @see #base(IRI)
-	 * @param base An absolute IRI to use as a base
+	 * @param base
+	 *            An absolute IRI to use as a base
 	 * @return An {@link RDFParserBuilder} that will use the specified base IRI
-	 */	
+	 */
 	RDFParserBuilder base(String base);
 
 	/**
 	 * Specify a source to parse.
 	 * <p>
-	 * The source set will not be accessed before the call to {@link #parse()}. 
+	 * The source set will not be read before the call to {@link #parse()}.
+	 * <p>
+	 * The InputStream will not be closed after parsing. The InputStream does
+	 * not need to support {@link InputStream#markSupported()}. The parser might
+	 * not consume the complete stream (e.g. the parser may not read beyond the
+	 * closing tag of <code>&lt;/rdf:Description&;gt</code>).
+	 * <p>
+	 * The {@link #contentType(RDFSyntax)} or {@link #contentType(String)}
+	 * SHOULD be set before calling {@link #parse()}.
+	 * <p>
+	 * The character set is assumed to be {@link StandardCharsets#UTF_8} unless
+	 * the {@link #contentType(String)} specifies otherwise.
 	 * <p>
-	 * The InputStream will not be closed after parsing. The
-	 * InputStream does not need to support {@link InputStream#markSupported()}.
+	 * The {@link #base(IRI)} or {@link #base(String)} MUST be set before
+	 * calling {@link #parse()}, unless the syntax does not permit relative
+	 * IRIs.
 	 * <p>
-	 * The {@link #contentType(RDFSyntax)} SHOULD be set unless the implementation
-	 * supports syntax guessing.
-	 * <p> 
-	 * The {@link #base(IRI)} MUST be set unless the syntax does not permit relative IRIs
-	 * (e.g.  {@link RDFSyntax#NTRIPLES}).
+	 * This method will override any source set with {@link #source(IRI)},
+	 * {@link #source(Path)} or {@link #source(String)}.
 	 * 
 	 * @param inputStream
-	 * @return
+	 *            An InputStream to consume
+	 * @return An {@link RDFParserBuilder} that will use the specified source.
 	 */
 	RDFParserBuilder source(InputStream inputStream);
 
@@ -186,7 +216,8 @@ public interface RDFParserBuilder {
 	/**
 	 * Parse the specified source.
 	 * 
-	 * @return The graph containing (at least) the parsed triples.
+	 * @return A Future that will return the graph containing (at least) the
+	 *         parsed triples.
 	 * 
 	 * @throws IOException
 	 *             If an error occurred while reading the source.
@@ -194,5 +225,5 @@ public interface RDFParserBuilder {
 	 *             If the builder is in an invalid state, e.g. a
 	 *             <code>source</code> has not been set.
 	 */
-	Graph parse() throws IOException, IllegalStateException;
+	Future<Graph> parse() throws IOException, IllegalStateException;
 }