incubator-any23-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ans...@apache.org
Subject svn commit: r1380396 - in /incubator/any23/trunk: ./ core/ core/src/main/java/org/apache/any23/extractor/rdf/ core/src/main/java/org/apache/any23/io/nquads/ core/src/main/java/org/apache/any23/writer/ core/src/test/java/org/apache/any23/io/nquads/ nqua...
Date Mon, 03 Sep 2012 23:03:30 GMT
Author: ansell
Date: Mon Sep  3 23:03:29 2012
New Revision: 1380396

URL: http://svn.apache.org/viewvc?rev=1380396&view=rev
Log:
ANY23-85 : Split out NQuads into its own module

Added:
    incubator/any23/trunk/nquads/
    incubator/any23/trunk/nquads/pom.xml
    incubator/any23/trunk/nquads/src/
    incubator/any23/trunk/nquads/src/main/
    incubator/any23/trunk/nquads/src/main/java/
    incubator/any23/trunk/nquads/src/main/java/org/
    incubator/any23/trunk/nquads/src/main/java/org/apache/
    incubator/any23/trunk/nquads/src/main/java/org/apache/any23/
    incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/
    incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/
    incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsParser.java
    incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsParserFactory.java
    incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsWriter.java
    incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsWriterFactory.java
    incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/package-info.java
    incubator/any23/trunk/nquads/src/test/
    incubator/any23/trunk/nquads/src/test/java/
    incubator/any23/trunk/nquads/src/test/java/org/
    incubator/any23/trunk/nquads/src/test/java/org/apache/
    incubator/any23/trunk/nquads/src/test/java/org/apache/any23/
    incubator/any23/trunk/nquads/src/test/java/org/apache/any23/io/
    incubator/any23/trunk/nquads/src/test/java/org/apache/any23/io/nquads/
    incubator/any23/trunk/nquads/src/test/java/org/apache/any23/io/nquads/NQuadsParserTest.java
    incubator/any23/trunk/nquads/src/test/java/org/apache/any23/io/nquads/NQuadsWriterTest.java
Removed:
    incubator/any23/trunk/core/src/main/java/org/apache/any23/io/nquads/
    incubator/any23/trunk/core/src/test/java/org/apache/any23/io/nquads/
Modified:
    incubator/any23/trunk/core/pom.xml
    incubator/any23/trunk/core/src/main/java/org/apache/any23/extractor/rdf/NQuadsExtractor.java
    incubator/any23/trunk/core/src/main/java/org/apache/any23/writer/NQuadsWriter.java
    incubator/any23/trunk/core/src/main/java/org/apache/any23/writer/NQuadsWriterFactory.java
    incubator/any23/trunk/pom.xml

Modified: incubator/any23/trunk/core/pom.xml
URL: http://svn.apache.org/viewvc/incubator/any23/trunk/core/pom.xml?rev=1380396&r1=1380395&r2=1380396&view=diff
==============================================================================
--- incubator/any23/trunk/core/pom.xml (original)
+++ incubator/any23/trunk/core/pom.xml Mon Sep  3 23:03:29 2012
@@ -37,6 +37,22 @@
     </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
+      <artifactId>apache-any23-csvutils</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apache-any23-mime</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apache-any23-nquads</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
       <artifactId>apache-any23-test-resources</artifactId>
       <version>${project.version}</version>
       <type>test-jar</type>
@@ -168,6 +184,11 @@
       <artifactId>mockito-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <scope>test</scope>
+    </dependency>
     <!-- END: Test Dependencies -->
   </dependencies>
 

Modified: incubator/any23/trunk/core/src/main/java/org/apache/any23/extractor/rdf/NQuadsExtractor.java
URL: http://svn.apache.org/viewvc/incubator/any23/trunk/core/src/main/java/org/apache/any23/extractor/rdf/NQuadsExtractor.java?rev=1380396&r1=1380395&r2=1380396&view=diff
==============================================================================
--- incubator/any23/trunk/core/src/main/java/org/apache/any23/extractor/rdf/NQuadsExtractor.java (original)
+++ incubator/any23/trunk/core/src/main/java/org/apache/any23/extractor/rdf/NQuadsExtractor.java Mon Sep  3 23:03:29 2012
@@ -22,6 +22,7 @@ import org.apache.any23.extractor.Extrac
 import org.apache.any23.extractor.ExtractorDescription;
 import org.apache.any23.extractor.ExtractorFactory;
 import org.apache.any23.extractor.SimpleExtractorFactory;
+import org.openrdf.rio.RDFParser;
 import org.openrdf.rio.helpers.RDFParserBase;
 
 import java.util.Arrays;
@@ -39,6 +40,7 @@ public class NQuadsExtractor extends Bas
                 "rdf-nq",
                 null,
                 Arrays.asList(
+                        "text/x-nquads;q=0.1",
                         "text/rdf+nq;q=0.1",
                         "text/nq;q=0.1",
                         "text/nquads;q=0.1",
@@ -61,7 +63,7 @@ public class NQuadsExtractor extends Bas
     }
 
     @Override
-    protected RDFParserBase getParser(ExtractionContext extractionContext, ExtractionResult extractionResult) {
+    protected RDFParser getParser(ExtractionContext extractionContext, ExtractionResult extractionResult) {
         return RDFParserFactory.getInstance().getNQuadsParser(
                 isVerifyDataType(), isStopAtFirstError(), extractionContext, extractionResult
         );

Modified: incubator/any23/trunk/core/src/main/java/org/apache/any23/writer/NQuadsWriter.java
URL: http://svn.apache.org/viewvc/incubator/any23/trunk/core/src/main/java/org/apache/any23/writer/NQuadsWriter.java?rev=1380396&r1=1380395&r2=1380396&view=diff
==============================================================================
--- incubator/any23/trunk/core/src/main/java/org/apache/any23/writer/NQuadsWriter.java (original)
+++ incubator/any23/trunk/core/src/main/java/org/apache/any23/writer/NQuadsWriter.java Mon Sep  3 23:03:29 2012
@@ -19,6 +19,9 @@ package org.apache.any23.writer;
 
 import java.io.OutputStream;
 
+import org.openrdf.rio.RDFFormat;
+import org.openrdf.rio.Rio;
+
 /**
  * Implementation of an <i>NQuads</i> writer.
  *
@@ -27,7 +30,7 @@ import java.io.OutputStream;
 public class NQuadsWriter extends RDFWriterTripleHandler implements FormatWriter {
 
     public NQuadsWriter(OutputStream os) {
-        super( new org.apache.any23.io.nquads.NQuadsWriter(os) );
+        super( Rio.createWriter(RDFFormat.NQUADS, os) );
     }
 
 }

Modified: incubator/any23/trunk/core/src/main/java/org/apache/any23/writer/NQuadsWriterFactory.java
URL: http://svn.apache.org/viewvc/incubator/any23/trunk/core/src/main/java/org/apache/any23/writer/NQuadsWriterFactory.java?rev=1380396&r1=1380395&r2=1380396&view=diff
==============================================================================
--- incubator/any23/trunk/core/src/main/java/org/apache/any23/writer/NQuadsWriterFactory.java (original)
+++ incubator/any23/trunk/core/src/main/java/org/apache/any23/writer/NQuadsWriterFactory.java Mon Sep  3 23:03:29 2012
@@ -29,7 +29,7 @@ import org.openrdf.rio.RDFFormat;
 @MetaInfServices
 public class NQuadsWriterFactory implements WriterFactory {
 
-    public static final String MIME_TYPE = "text/plain";
+    public static final String MIME_TYPE = RDFFormat.NQUADS.getDefaultMIMEType();
     public static final String IDENTIFIER = "nquads";
 
     /**

Added: incubator/any23/trunk/nquads/pom.xml
URL: http://svn.apache.org/viewvc/incubator/any23/trunk/nquads/pom.xml?rev=1380396&view=auto
==============================================================================
--- incubator/any23/trunk/nquads/pom.xml (added)
+++ incubator/any23/trunk/nquads/pom.xml Mon Sep  3 23:03:29 2012
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<project
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+  xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>apache-any23</artifactId>
+    <groupId>org.apache.any23</groupId>
+    <version>0.7.1-incubating-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+  <artifactId>apache-any23-nquads</artifactId>
+  <name>Apache Any23 :: NQuads Parser and Writer</name>
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apache-any23-test-resources</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+      <type>test-jar</type>
+    </dependency>
+    <dependency>
+      <groupId>org.openrdf.sesame</groupId>
+      <artifactId>sesame-model</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.openrdf.sesame</groupId>
+      <artifactId>sesame-rio-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.openrdf.sesame</groupId>
+      <artifactId>sesame-rio-ntriples</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.kohsuke.metainf-services</groupId>
+      <artifactId>metainf-services</artifactId>
+      <scope>compile</scope>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
+

Added: incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsParser.java
URL: http://svn.apache.org/viewvc/incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsParser.java?rev=1380396&view=auto
==============================================================================
--- incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsParser.java (added)
+++ incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsParser.java Mon Sep  3 23:03:29 2012
@@ -0,0 +1,742 @@
+/*
+ * 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.any23.io.nquads;
+
+import org.openrdf.model.BNode;
+import org.openrdf.model.Resource;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.Value;
+import org.openrdf.model.datatypes.XMLDatatypeUtil;
+import org.openrdf.model.impl.URIImpl;
+import org.openrdf.rio.ParseLocationListener;
+import org.openrdf.rio.RDFFormat;
+import org.openrdf.rio.RDFHandler;
+import org.openrdf.rio.RDFHandlerException;
+import org.openrdf.rio.RDFParseException;
+import org.openrdf.rio.helpers.RDFParserBase;
+import org.openrdf.rio.ntriples.NTriplesUtil;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+
+/**
+ * <i>N-Quads</i> parser implementation based on the
+ * {@link org.openrdf.rio.RDFParser} interface.
+ * See the format specification <a href="http://sw.deri.org/2008/07/n-quads/">here</a>.
+ *
+ * @author Michele Mostarda (mostarda@fbk.eu)
+ * @see org.openrdf.rio.RDFParser
+ */
+public class NQuadsParser extends RDFParserBase {
+
+    /**
+     * Location listener acquired when parsing started.
+     */
+    private ParseLocationListener locationListener;
+
+    /**
+     * RDF handler acquired when parsing started.
+     */
+    private RDFHandler rdfHandler;
+
+    /**
+     * Current row, col and marker trackers.
+     */
+    private int row, col, mark;
+
+    public NQuadsParser() {}
+
+    public RDFFormat getRDFFormat() {
+        return RDFFormat.NQUADS;
+    }
+
+    public void parse(Reader reader, String baseURI)
+    throws IOException, RDFParseException, RDFHandlerException {
+        if(reader == null) {
+            throw new NullPointerException("reader cannot be null.");
+        }
+        if(baseURI == null) {
+            throw new NullPointerException("baseURI cannot be null.");
+        }
+        
+        try {
+            row = col = 1;
+
+            locationListener = getParseLocationListener();
+            rdfHandler = getRDFHandler();
+
+            setBaseURI(baseURI);
+
+            final BufferedReader br = new BufferedReader( reader );
+            if( rdfHandler != null ) {
+                rdfHandler.startRDF();
+            }
+            while( parseLine(br) ) {
+                nextRow();
+            }
+        } finally {
+            if(rdfHandler != null) {
+                rdfHandler.endRDF();
+            }
+            clear();
+            clearBNodeIDMap();
+        }
+    }
+
+    public synchronized void parse(InputStream is, String baseURI)
+    throws IOException, RDFParseException, RDFHandlerException {
+        if(is == null) {
+            throw new NullPointerException("inputStream cannot be null.");
+        }
+        if(baseURI == null) {
+            throw new NullPointerException("baseURI cannot be null.");
+        }
+        
+        // NOTE: Sindice needs to be able to support UTF-8 native N-Quads documents, so the charset cannot be US-ASCII
+        this.parse(new InputStreamReader(is, Charset.forName("UTF-8")), baseURI);
+    }
+
+    /**
+     * Moves to the next row, resets the column.
+     */
+    private void nextRow() {
+        col = 1;
+        row++;
+        if(locationListener != null) {
+            locationListener.parseLocationUpdate(row, col);
+        }
+    }
+
+    /**
+     * Moves to the next column.
+     */
+    private void nextCol() {
+        col++;
+        if(locationListener != null) {
+            locationListener.parseLocationUpdate(row, col);
+        }
+    }
+
+    /**
+     * Reads the next char.
+     *
+     * @param br
+     * @return the next read char.
+     * @throws IOException
+     */
+    private char readChar(BufferedReader br) throws IOException {
+        final int c = br.read();
+        if(c == -1) {
+            throw new EOS();
+        }
+        nextCol();
+        return (char) c;
+    }
+
+    /**
+     * Reads an unicode char with pattern <code>\\uABCD</code>.
+     *
+     * @param br input reader.
+     * @return read char.
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    private char readUnicode(BufferedReader br) throws IOException, RDFParseException {
+        final char[] unicodeSequence = new char[4];
+        for(int i = 0; i < unicodeSequence.length; i++) {
+            unicodeSequence[i] = readChar(br);
+        }
+        final String unicodeCharStr = new String(unicodeSequence);
+        try {
+            return (char) Integer.parseInt(unicodeCharStr, 16);
+        } catch (NumberFormatException nfe) {
+            reportError("Error while converting unicode char '\\u" + unicodeCharStr + "'", row, col);
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Marks the buffered input stream with the current location.
+     *
+     * @param br
+     */
+    private void mark(BufferedReader br) throws IOException {
+        mark = col;
+        br.mark(5);
+    }
+
+    /**
+     * Resets the buffered input stream and update the new location.
+     *
+     * @param br
+     * @throws IOException
+     */
+    private void reset(BufferedReader br) throws IOException {
+        col = mark;
+        br.reset();
+        if(locationListener != null) {
+            locationListener.parseLocationUpdate(row, col);
+        }
+    }
+
+    /**
+     * Asserts to read a specific char.
+     *
+     * @param br
+     * @param c
+     * @throws IOException
+     */
+    private void assertChar(BufferedReader br, char c) throws IOException, RDFParseException {
+        final char read = readChar(br);
+        if(read != c) {
+            throw new RDFParseException(
+                    String.format("Unexpected char '%s', expected '%s'", read, c),
+                    row, col
+            );
+        }
+    }
+
+    /**
+     * Consumes the reader until the next carriage return.
+     *
+     * @param br
+     * @throws IOException
+     */
+    private void consumeBrokenLine(BufferedReader br) throws IOException {
+        char c;
+        while (true) {
+            mark(br);
+            c = readChar(br);
+            if (c == '\n') {
+                return;
+            }
+        }
+    }
+
+    /**
+     * Parsers an <i>NQuads</i> line.
+     *
+     * @param br input stream reader containing NQuads.
+     * @return <code>false</code> if the parsing completed, <code>true</code> otherwise.
+     * @throws IOException
+     * @throws RDFParseException
+     * @throws RDFHandlerException
+     */
+    private boolean parseLine(BufferedReader br)
+    throws IOException, RDFParseException, RDFHandlerException {
+
+        if(!consumeSpacesAndNotEOS(br)) {
+            return false;
+        }
+
+        // Consumes empty line or line comment.
+        try {
+            if(consumeEmptyLine(br)) return true;
+            if( consumeComment(br) ) return true;
+        } catch (EOS eos) {
+            return false;
+        }
+
+        final Resource sub;
+        final URI      pred;
+        final Value    obj;
+        final URI      context;
+        try {
+            sub = parseSubject(br);
+            consumeSpaces(br);
+            pred = parsePredicate(br);
+            consumeSpaces(br);
+            obj = parseObject(br);
+            consumeSpaces(br);
+            context = parseContextAndOrDot(br);
+        } catch (EOS eos) {
+            reportFatalError("Unexpected end of stream.", row, col);
+            throw new IllegalStateException();
+        } catch (Exception e) {
+            if(super.stopAtFirstError()) {
+                if(e instanceof RDFParseException)
+                    throw (RDFParseException) e;
+                else
+                    throw new RDFParseException(e, row, col);
+            } else { // Remove rest of broken line and report error.
+                consumeBrokenLine(br);
+                reportError(e.getMessage(), row, col);
+                return true;
+            }
+        }
+
+        assert sub  != null : "Subject cannot be null.";
+        assert pred != null : "Predicate cannot be null.";
+        assert obj  != null : "Object cannot be null.";
+        notifyStatement(sub, pred, obj, context);
+
+        if(!consumeSpacesAndNotEOS(br)) {
+            return false;
+        }
+        return readChar(br) == '\n';
+    }
+
+    /**
+     * Consumes the line if empty (contains just a carriage return).
+     *
+     * @param br input NQuads stream.
+     * @return <code>true</code> if the line is empty.
+     * @throws IOException if an error occurs while consuming stream.
+     */
+    private boolean consumeEmptyLine(BufferedReader br) throws IOException {
+        char c;
+        mark(br);
+        c = readChar(br);
+        if (c == '\n') {
+            return true;
+        } else {
+            reset(br);
+            return false;
+        }
+    }
+
+    /**
+     * Consumes all subsequent spaces and returns true, if End Of Stream is reached instead returns false.
+     * @param br input NQuads stream reader.
+     * @return <code>true</code> if there are other chars to be consumed.
+     * @throws IOException if an error occurs while consuming stream.
+     */
+    private boolean consumeSpacesAndNotEOS(BufferedReader br) throws IOException {
+        try {
+            consumeSpaces(br);
+            return true;
+        } catch (EOS eos) {
+            return false;
+        }
+    }
+
+    /**
+     * Consumes a comment if any.
+     *
+     * @param br input NQuads stream reader.
+     * @return <code>true</code> if comment has been consumed, false otherwise.
+     * @throws IOException
+     */
+    private boolean consumeComment(BufferedReader br) throws IOException {
+        char c;
+        mark(br);
+        c = readChar(br);
+        if (c == '#') {
+            mark(br);
+            while (readChar(br) != '\n');
+            mark(br);
+            return true;
+        } else {
+            reset(br);
+            return false;
+        }
+    }
+
+    /**
+     * Notifies the parsed statement to the {@link RDFHandler}.
+     *
+     * @param sub
+     * @param pred
+     * @param obj
+     * @param context
+     * @throws RDFParseException
+     * @throws RDFHandlerException
+     */
+    private void notifyStatement(Resource sub, URI pred, Value obj, URI context)
+    throws RDFParseException, RDFHandlerException {
+        Statement statement = super.createStatement(sub, pred, obj, context);
+        if (rdfHandler != null) {
+            try {
+                rdfHandler.handleStatement(statement);
+            } catch (RDFHandlerException rdfhe) {
+                reportFatalError(rdfhe);
+                throw rdfhe;
+            }
+        }
+    }
+
+    /**
+     * Consumes spaces until a non space char is detected.
+     *
+     * @param br input stream reader from which consume spaces.
+     * @throws IOException
+     */
+    private void consumeSpaces(BufferedReader br) throws IOException {
+        char c;
+        while(true) {
+            mark(br);
+            c = readChar(br);
+            if(c == ' ' || c == '\r' || c == '\f' || c == '\t') {
+                mark(br);
+            } else {
+                break;
+            }
+        }
+        reset(br);
+    }
+
+    /**
+     * Consumes the dot at the end of NQuads line.
+     *
+     * @param br
+     * @throws IOException
+     */
+    private void parseDot(BufferedReader br) throws IOException, RDFParseException {
+        assertChar(br, '.');
+    }
+
+    /**
+     * Parses a URI enclosed within &lt; and &gt; brackets.
+     * @param br
+     * @return the parsed URI.
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    private URI parseURI(BufferedReader br) throws IOException, RDFParseException {
+        assertChar(br, '<');
+
+        StringBuilder sb = new StringBuilder();
+        char c;
+        while(true) {
+            c = readChar(br);
+            if(c != '>') {
+                sb.append(c);
+            } else {
+                break;
+            }
+        }
+        mark(br);
+
+        try {
+            // TODO - LOW: used to unescape \\uXXXX unicode chars. Unify with #printEscaped().
+            String uriStr = NTriplesUtil.unescapeString( sb.toString() );
+            URI uri;
+            if(uriStr.charAt(0) == '#') {
+                uri = super.resolveURI(uriStr);
+            } else {
+                uri = super.createURI(uriStr);
+            }
+            return uri;
+        } catch (RDFParseException rdfpe) {
+            reportFatalError(rdfpe, row, col);
+            throw rdfpe;
+        }
+    }
+
+    /**
+     * Parses a BNode.
+     *
+     * @param br the buffered input stream.
+     * @return the generated bnode.
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    private BNode parseBNode(BufferedReader br) throws IOException, RDFParseException {
+        assertChar(br, '_');
+        assertChar(br, ':');
+
+        char c;
+        StringBuilder sb = new StringBuilder();
+        while(true) {
+            c = readChar(br);
+            if(c != ' ' && c != '<') {
+                sb.append(c);
+                mark(br);
+            } else {
+                break;
+            }
+        }
+        reset(br);
+
+        try {
+            return createBNode( sb.toString() );
+        } catch (RDFParseException rdfpe) {
+            reportFatalError(rdfpe, row, col);
+            throw rdfpe;
+        }
+    }
+
+    /**
+     * Parses a literal attribute that can be either the language or the data type.
+     *
+     * @param br
+     * @return the literal attribute.
+     * @throws IOException
+     */
+    private LiteralAttribute parseLiteralAttribute(BufferedReader br) throws IOException, RDFParseException {
+        char c = readChar(br);
+        if(c != '^' && c != '@') {
+            reset(br);
+            return null;
+        }
+
+        boolean isLang = true;
+        if(c == '^') {
+            isLang = false;
+            assertChar(br, '^');
+        }
+
+        final String attribute;
+        if (isLang) { // Read until space or context begin.
+            final StringBuilder sb = new StringBuilder();
+            while (true) {
+                c = readChar(br);
+                if (c != ' ' && c != '<') {
+                    mark(br);
+                    sb.append(c);
+                } else {
+                    reset(br);
+                    break;
+                }
+            }
+            attribute = sb.toString();
+        }  else {
+            attribute = parseURI(br).stringValue();
+        }
+
+        return new LiteralAttribute(isLang, attribute);
+    }
+
+    /**
+     * Validates and normalize the value of a literal on the basis of the datat ype handling policy and
+     * the associated data type.
+     *
+     * @param value
+     * @param datatype
+     * @return the normalized data type. It depends on the data type handling policy and the specified data type.
+     * @throws RDFParseException
+     */
+    private String validateAndNormalizeLiteral(String value, URI datatype) throws RDFParseException {
+        DatatypeHandling dh = datatypeHandling();
+        if(dh.equals( DatatypeHandling.IGNORE )) {
+            return value;
+        }
+
+        if ( dh.equals(DatatypeHandling.VERIFY) ) {
+            if( ! XMLDatatypeUtil.isBuiltInDatatype(datatype)){
+                return value;
+            }
+            if( ! XMLDatatypeUtil.isValidValue(value, datatype) ) {
+                throw new RDFParseException(
+                        String.format("Illegal literal value '%s' with datatype %s", value, datatype.stringValue() ),
+                        row, col
+                );
+            }
+            return value;
+        } else if( dh.equals(DatatypeHandling.NORMALIZE) ) {
+            return XMLDatatypeUtil.normalize(value, datatype);
+        } else {
+            throw new IllegalArgumentException( String.format("Unsupported datatype handling: %s", dh) );
+        }
+    }
+
+    /**
+     * Prints the escaped version of the given char c.
+     *
+     * @param c escaped char.
+     * @param sb output string builder.
+     */
+    private void printEscaped(char c, StringBuilder sb) {
+        if(c == 'b') {
+            sb.append('\b');
+            return;
+        }
+        if(c == 'f') {
+            sb.append('\f');
+            return;
+        }
+        if(c == 'n') {
+            sb.append('\n');
+            return;
+        }
+        if(c == 'r') {
+            sb.append('\r');
+            return;
+        }
+        if(c == 't') {
+            sb.append('\t');
+            return;
+        }
+    }
+
+    /**
+     * Parses a literal.
+     *
+     * @param br
+     * @return the parsed literal.
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    private Value parseLiteral(BufferedReader br) throws IOException, RDFParseException {
+        assertChar(br, '"');
+
+        char c;
+        boolean escaped = false;
+        StringBuilder sb = new StringBuilder();
+        while(true) {
+            c = readChar(br);
+            if( c == '\\' ) {
+                if(escaped) {
+                    escaped = false;
+                    sb.append(c);
+                } else {
+                    escaped = true;
+                }
+                continue;
+            } else if(c == '"' && !escaped) {
+                break;
+            }
+            if(escaped) {
+                if(c == 'u') {
+                    char unicodeChar = readUnicode(br);
+                    sb.append(unicodeChar);
+                } else {
+                    printEscaped(c, sb);
+                }
+                escaped = false;
+            } else {
+                sb.append(c);
+            }
+        }
+        mark(br);
+
+        LiteralAttribute lt = parseLiteralAttribute(br);
+
+        final String value = sb.toString();
+        if(lt == null) {
+            return createLiteral(value, null, null);
+        }else if(lt.isLang) {
+            return createLiteral(
+                    value,
+                    lt.value,
+                    null
+            );
+        } else {
+            URI literalType = null;
+            try {
+                literalType = new URIImpl(lt.value);
+            } catch (Exception e) {
+                reportError( String.format("Error while parsing literal type '%s'", lt.value), row, col );
+            }
+            return createLiteral(
+                    validateAndNormalizeLiteral(value, literalType),
+                    null,
+                    literalType
+            );
+        }
+    }
+
+    /**
+     * Parses the subject sequence.
+     *
+     * @param br
+     * @return the corresponding URI object.
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    private Resource parseSubject(BufferedReader br) throws IOException, RDFParseException {
+        mark(br);
+        char c = readChar(br);
+        reset(br);
+        if( c == '<' ) {
+            return parseURI(br);
+        } else {
+            return parseBNode(br);
+        }
+    }
+
+    /**
+     * Parses the predicate URI.
+     *
+     * @param br
+     * @return the corresponding URI object.
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    private URI parsePredicate(BufferedReader br) throws IOException, RDFParseException {
+        return parseURI(br);
+    }
+
+    /**
+     * Parses the the object sequence.
+     *
+     * @param br
+     * @return the corresponding URI object.
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    private Value parseObject(BufferedReader br) throws IOException, RDFParseException {
+        mark(br);
+        char c = readChar(br);
+        reset(br);
+        if( c == '<' ) {
+            return parseURI(br);
+        } else if( c == '_') {
+            return parseBNode(br);
+        } else {
+            return parseLiteral(br);
+        }
+    }
+
+    /**
+     * Represents a literal with its attribute value that can be either a language or a data type.
+     */
+    class LiteralAttribute {
+        final boolean isLang;
+        final String value;
+
+        LiteralAttribute(boolean lang, String value) {
+            isLang = lang;
+            this.value = value;
+        }
+    }
+
+    /**
+     * Parses the context if any.
+     *
+     * @param br
+     * @return the context URI or null if not found.
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    private URI parseContextAndOrDot(BufferedReader br) throws IOException, RDFParseException {
+        mark(br);
+        final char c = readChar(br);
+        reset(br);
+        if(c == '<') {
+            final URI context = parseURI(br);
+            consumeSpaces(br);
+            parseDot(br);
+            return context;
+        } else {
+            parseDot(br);
+            return null;
+        }
+    }
+
+    /**
+     * Defines the End Of Stream exception.
+     */
+    class EOS extends IOException {}
+
+}

Added: incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsParserFactory.java
URL: http://svn.apache.org/viewvc/incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsParserFactory.java?rev=1380396&view=auto
==============================================================================
--- incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsParserFactory.java (added)
+++ incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsParserFactory.java Mon Sep  3 23:03:29 2012
@@ -0,0 +1,45 @@
+/*
+ * 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.any23.io.nquads;
+
+import org.kohsuke.MetaInfServices;
+import org.openrdf.rio.RDFFormat;
+import org.openrdf.rio.RDFParser;
+import org.openrdf.rio.RDFParserFactory;
+
+/**
+ * Implementation of {@link org.openrdf.rio.RDFParserFactory} for <code>NQuads</code>.
+ *
+ * @author Michele Mostarda (mostarda@fbk.eu)
+ */
+@MetaInfServices
+public class NQuadsParserFactory implements RDFParserFactory {
+
+    public NQuadsParserFactory() {}
+
+    @Override
+    public RDFFormat getRDFFormat() {
+        return RDFFormat.NQUADS;
+    }
+
+    @Override
+    public RDFParser getParser() {
+        return new NQuadsParser();
+    }
+
+}

Added: incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsWriter.java
URL: http://svn.apache.org/viewvc/incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsWriter.java?rev=1380396&view=auto
==============================================================================
--- incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsWriter.java (added)
+++ incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsWriter.java Mon Sep  3 23:03:29 2012
@@ -0,0 +1,273 @@
+/*
+ * 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.any23.io.nquads;
+
+import org.openrdf.model.BNode;
+import org.openrdf.model.Literal;
+import org.openrdf.model.Resource;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.Value;
+import org.openrdf.rio.RDFFormat;
+import org.openrdf.rio.RDFHandlerException;
+import org.openrdf.rio.RDFWriter;
+import org.openrdf.rio.ntriples.NTriplesUtil;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <i>N-Quads</i> implementation of an {@link org.openrdf.rio.RDFWriter}.
+ * See the format specification <a href="http://sw.deri.org/2008/07/n-quads/">here</a>.
+ *
+ * @author Michele Mostarda (mostarda@fbk.eu)
+ */
+public class NQuadsWriter implements RDFWriter {
+
+    /**
+     * The table maintaining namespaces.
+     */
+    private Map<String,String> namespaceTable;
+
+    /**
+     * The output writer.
+     */
+    private Writer writer;
+
+    /**
+     * Maintain the started status.
+     */
+    private boolean started = false;
+
+    public NQuadsWriter(OutputStream os) {
+        this( new OutputStreamWriter(os) );
+    }
+
+    public NQuadsWriter(Writer w) {
+        if(w == null) {
+            throw new NullPointerException("the writer cannot be null.");
+        }
+        writer = w;
+    }
+
+    public RDFFormat getRDFFormat() {
+        return RDFFormat.NQUADS;
+    }
+
+    public void startRDF() throws RDFHandlerException {
+        if(started) {
+            throw new IllegalStateException("Parsing already started.");
+        }
+        started = true;
+    }
+
+    public void endRDF() throws RDFHandlerException {
+        if(!started) {
+            throw new IllegalStateException("Parsing never started.");
+        }
+
+        try {
+            writer.flush();
+        } catch (IOException ioe) {
+            throw new RDFHandlerException("Error while flushing writer.", ioe);
+        } finally {
+            started = false;
+            if(namespaceTable != null) {
+                namespaceTable.clear();
+            }
+        }
+    }
+
+    public void handleNamespace(String ns, String uri) throws RDFHandlerException {
+        if(!started) {
+            throw new IllegalStateException("Parsing never started.");
+        }
+
+        if(namespaceTable == null) {
+            namespaceTable = new HashMap<String, String>();
+        }
+        namespaceTable.put(ns, NTriplesUtil.escapeString(uri) );
+    }
+
+    public void handleStatement(Statement statement) throws RDFHandlerException {
+        if(!started) {
+            throw new IllegalStateException("Cannot handle statement without start parsing first.");
+        }
+
+        try {
+            printSubject(statement);
+            printSpace();
+            printPredicate(statement);
+            printSpace();
+            printObject(statement);
+            printSpace();
+            printGraph(statement);
+            printCloseStatement();
+        } catch (IOException ioe) {
+            throw new RDFHandlerException("An error occurred while printing statement.", ioe);
+        }
+    }
+
+    public void handleComment(String comment) throws RDFHandlerException {
+        try {
+            writer.write("# ");
+            writer.write(comment);
+            writer.append('\n');
+        } catch (IOException ioe) {
+            throw new RDFHandlerException("An error occurred while printing comment.", ioe);
+        }
+    }
+
+    /**
+     * Prints out a space.
+     *
+     * @throws IOException
+     */
+    private void printSpace() throws IOException {
+        writer.append(' ');
+    }
+
+    /**
+     * Prints out the close statement.
+     * 
+     * @throws IOException
+     */
+    private void printCloseStatement() throws IOException {
+        writer.append(" .\n");
+    }
+
+    /**
+     * Prints out a URI string, replacing the existing prefix if found.
+     * 
+     * @param uri the URI to print.
+     * @throws IOException
+     */
+    private void printURI(URI uri) throws IOException {
+        final String uriString = uri.stringValue();
+        int splitIdx = 0;
+        String namespace = null;
+        if(namespaceTable != null) {
+            splitIdx = uriString.indexOf(':');
+            if (splitIdx > 0) {
+                String prefix = uriString.substring(0, splitIdx);
+                namespace = namespaceTable.get(prefix);
+            }
+        }
+
+        if (namespace != null) {
+            writer.append('<');
+            writer.append(namespace);
+            writer.append( NTriplesUtil.escapeString(uriString.substring(splitIdx)) );
+            writer.append('>');
+        } else {
+            writer.append('<');
+            writer.append( NTriplesUtil.escapeString(uriString) );
+            writer.append('>');
+        }
+    }
+
+    /**
+     * Prints out the bnode.
+     *
+     * @param b bnode value.
+     * @throws IOException
+     */
+    private void printBNode(BNode b) throws IOException {
+        writer.append( NTriplesUtil.toNTriplesString(b) );
+    }
+
+    /**
+     * Prints out the resource.
+     *
+     * @param r resource value.
+     * @throws java.io.IOException
+     */
+    private void printResource(Resource r) throws IOException {
+        if(r instanceof BNode) {
+            printBNode((BNode) r);
+        } else if(r instanceof URI) {
+            printURI((URI) r);
+        } else {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Prints out a literal value.
+     *
+     * @param l literal value.
+     * @throws java.io.IOException
+     */
+    private void printLiteral(Literal l) throws IOException {
+        writer.append( NTriplesUtil.toNTriplesString(l) );
+    }
+
+    /**
+     * Prints out the subject.
+     * 
+     * @param s
+     * @throws IOException
+     */
+    private void printSubject(Statement s) throws IOException {
+        printResource( s.getSubject() );
+    }
+
+    /**
+     * Prints out the predicate.
+     *
+     * @param s
+     * @throws IOException
+     */
+    private void printPredicate(Statement s) throws IOException {
+        printURI( s.getPredicate() );
+    }
+
+    /**
+     * Prints out the object, handling all the logic to manage
+     * the literal data type / language attribute.
+     *
+     * @param s
+     * @throws IOException
+     */
+    private void printObject(Statement s) throws IOException {
+        Value v = s.getObject();
+        if(v instanceof Resource) {
+            printResource((Resource) v);
+            return;
+        }
+        printLiteral( (Literal) v );
+    }
+
+    /**
+     * Prints out the graph.
+     *
+     * @param s
+     * @throws IOException
+     */
+    private void printGraph(Statement s) throws IOException {
+        Resource graph = s.getContext();
+        if(graph != null) {
+            printResource( s.getContext() );
+        }
+    }
+
+}

Added: incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsWriterFactory.java
URL: http://svn.apache.org/viewvc/incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsWriterFactory.java?rev=1380396&view=auto
==============================================================================
--- incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsWriterFactory.java (added)
+++ incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/NQuadsWriterFactory.java Mon Sep  3 23:03:29 2012
@@ -0,0 +1,51 @@
+/*
+ * 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.any23.io.nquads;
+
+import org.kohsuke.MetaInfServices;
+import org.openrdf.rio.RDFFormat;
+import org.openrdf.rio.RDFWriter;
+import org.openrdf.rio.RDFWriterFactory;
+
+import java.io.OutputStream;
+import java.io.Writer;
+
+/**
+ * Implementation of {@link RDFWriterFactory} for <code>NQuads</code>.
+ *
+ * @author Michele Mostarda (mostarda@fbk.eu)
+ */
+@MetaInfServices
+public class NQuadsWriterFactory implements RDFWriterFactory {
+
+    @Override
+    public RDFFormat getRDFFormat() {
+        return RDFFormat.NQUADS;
+    }
+
+    @Override
+    public RDFWriter getWriter(OutputStream outputStream) {
+        return new NQuadsWriter(outputStream);
+    }
+
+    @Override
+    public RDFWriter getWriter(Writer writer) {
+        return new NQuadsWriter(writer);
+    }
+
+}

Added: incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/package-info.java
URL: http://svn.apache.org/viewvc/incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/package-info.java?rev=1380396&view=auto
==============================================================================
--- incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/package-info.java (added)
+++ incubator/any23/trunk/nquads/src/main/java/org/apache/any23/io/nquads/package-info.java Mon Sep  3 23:03:29 2012
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+/**
+ * This package contains an <i><a href="http://sw.deri.org/2008/07/n-quads/">NQuads</a></i>
+ * parser and writer based on the <i><a href="http://www.openrdf.org/">Sesame</a> API</i>.
+ */
+package org.apache.any23.io.nquads;
\ No newline at end of file

Added: incubator/any23/trunk/nquads/src/test/java/org/apache/any23/io/nquads/NQuadsParserTest.java
URL: http://svn.apache.org/viewvc/incubator/any23/trunk/nquads/src/test/java/org/apache/any23/io/nquads/NQuadsParserTest.java?rev=1380396&view=auto
==============================================================================
--- incubator/any23/trunk/nquads/src/test/java/org/apache/any23/io/nquads/NQuadsParserTest.java (added)
+++ incubator/any23/trunk/nquads/src/test/java/org/apache/any23/io/nquads/NQuadsParserTest.java Mon Sep  3 23:03:29 2012
@@ -0,0 +1,658 @@
+/*
+ * 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.any23.io.nquads;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.openrdf.model.BNode;
+import org.openrdf.model.Literal;
+import org.openrdf.model.Resource;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.Value;
+import org.openrdf.model.impl.URIImpl;
+import org.openrdf.rio.ParseLocationListener;
+import org.openrdf.rio.RDFHandler;
+import org.openrdf.rio.RDFHandlerException;
+import org.openrdf.rio.RDFParseException;
+import org.openrdf.rio.RDFParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.hamcrest.core.Is.is;
+
+/**
+ * Test case for {@link NQuadsParser}.
+ *
+ * @author Michele Mostarda (mostarda@fbk.eu)
+ */
+public class NQuadsParserTest {
+
+    private static final Logger logger = LoggerFactory.getLogger(NQuadsParser.class);
+
+    private NQuadsParser parser;
+
+    @Before
+    public void setUp() {
+        parser = new NQuadsParser();
+        parser.setVerifyData(true);
+        parser.setDatatypeHandling(RDFParser.DatatypeHandling.VERIFY);
+        parser.setStopAtFirstError(true);
+    }
+
+    @After
+    public void tearDown() {
+        parser = null;
+    }
+
+    /**
+     * Tests the correct behavior with incomplete input.
+     *
+     * @throws RDFHandlerException
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    @Test(expected = RDFParseException.class)
+    public void testIncompleteParsing() throws RDFHandlerException, IOException, RDFParseException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+                "<http://s> <http://p> <http://o> <http://g>".getBytes()
+        );
+        parser.parse(bais, "http://base-uri");
+    }
+
+    /**
+     * Tests parsing of empty lines and comments.
+     *
+     * @throws java.io.IOException
+     */
+    @Test
+    public void testParseEmptyLinesAndComments() throws RDFHandlerException, IOException, RDFParseException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+            "  \n\n\n# This is a comment\n\n#this is another comment."
+            .getBytes()
+        );
+        final TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setRDFHandler(rdfHandler);
+        parser.parse(bais, "http://test.base.uri");
+        Assert.assertEquals(rdfHandler.getStatements().size(), 0);
+    }
+
+    /**
+     * Tests basic N-Quads parsing.
+     *
+     * @throws RDFHandlerException
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    @Test
+    public void testParseBasic() throws RDFHandlerException, IOException, RDFParseException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+            "<http://www.v/dat/4b><http://www.w3.org/20/ica#dtend><http://sin/value/2><http://sin.siteserv.org/def/>."
+            .getBytes()
+        );
+        final TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setRDFHandler(rdfHandler);
+        parser.parse(bais, "http://test.base.uri");
+        Assert.assertThat(rdfHandler.getStatements().size(), is(1));
+        final Statement statement = rdfHandler.getStatements().get(0);
+        Assert.assertEquals("http://www.v/dat/4b", statement.getSubject().stringValue());
+        Assert.assertEquals("http://www.w3.org/20/ica#dtend", statement.getPredicate().stringValue());
+        Assert.assertTrue(statement.getObject() instanceof URI);
+        Assert.assertEquals("http://sin/value/2", statement.getObject().stringValue());
+        Assert.assertEquals("http://sin.siteserv.org/def/", statement.getContext().stringValue());
+    }
+
+    /**
+     * Tests basic N-Quads parsing with blank node.
+     *
+     * @throws RDFHandlerException
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    @Test
+    public void testParseBasicBNode() throws RDFHandlerException, IOException, RDFParseException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+            "_:123456768<http://www.w3.org/20/ica#dtend><http://sin/value/2><http://sin.siteserv.org/def/>."
+            .getBytes()
+        );
+        final TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setRDFHandler(rdfHandler);
+        parser.parse(bais, "http://test.base.uri");
+        Assert.assertThat(rdfHandler.getStatements().size(), is(1));
+        final Statement statement = rdfHandler.getStatements().get(0);
+        Assert.assertTrue(statement.getSubject() instanceof BNode);
+        Assert.assertEquals("http://www.w3.org/20/ica#dtend", statement.getPredicate().stringValue());
+        Assert.assertTrue(statement.getObject() instanceof URI);
+        Assert.assertEquals("http://sin/value/2", statement.getObject().stringValue());
+        Assert.assertEquals("http://sin.siteserv.org/def/", statement.getContext().stringValue());
+    }
+
+    /**
+     * Tests basic N-Quads parsing with literal.
+     *
+     * @throws RDFHandlerException
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    @Test
+    public void testParseBasicLiteral() throws RDFHandlerException, IOException, RDFParseException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+            "_:123456768<http://www.w3.org/20/ica#dtend>\"2010-05-02\"<http://sin.siteserv.org/def/>."
+            .getBytes()
+        );
+        final TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setRDFHandler(rdfHandler);
+        parser.parse(bais, "http://test.base.uri");
+        Assert.assertThat(rdfHandler.getStatements().size(), is(1));
+        final Statement statement = rdfHandler.getStatements().get(0);
+        Assert.assertTrue(statement.getSubject() instanceof BNode);
+        Assert.assertEquals("http://www.w3.org/20/ica#dtend", statement.getPredicate().stringValue());
+        Assert.assertTrue(statement.getObject() instanceof Literal);
+        Assert.assertEquals("2010-05-02", statement.getObject().stringValue());
+        Assert.assertEquals("http://sin.siteserv.org/def/", statement.getContext().stringValue());
+    }
+
+    /**
+     * Tests N-Quads parsing with literal and language.
+     * 
+     * @throws RDFHandlerException
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    @Test
+    public void testParseBasicLiteralLang() throws RDFHandlerException, IOException, RDFParseException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+            "<http://www.v/dat/4b2-21><http://www.w3.org/20/ica#dtend>\"2010-05-02\"@en<http://sin.siteserv.org/def/>."
+            .getBytes()
+        );
+        final TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setRDFHandler(rdfHandler);
+        parser.parse(bais, "http://test.base.uri");
+        final Statement statement = rdfHandler.getStatements().get(0);
+        Assert.assertEquals("http://www.v/dat/4b2-21", statement.getSubject().stringValue());
+        Assert.assertEquals("http://www.w3.org/20/ica#dtend", statement.getPredicate().stringValue());
+        Assert.assertTrue(statement.getObject() instanceof Literal);
+        Literal object = (Literal) statement.getObject();
+        Assert.assertEquals("2010-05-02", object.stringValue());
+        Assert.assertEquals("en", object.getLanguage());
+        Assert.assertNull("en", object.getDatatype());
+        Assert.assertEquals("http://sin.siteserv.org/def/", statement.getContext().stringValue());
+    }
+
+    /**
+     * Tests N-Quads parsing with literal and datatype.
+     * 
+     * @throws RDFHandlerException
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    @Test
+    public void testParseBasicLiteraDatatype() throws RDFHandlerException, IOException, RDFParseException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+            ("<http://www.v/dat/4b2-21>" +
+             "<http://www.w3.org/20/ica#dtend>" +
+             "\"2010\"^^<http://www.w3.org/2001/XMLSchema#integer>" +
+             "<http://sin.siteserv.org/def/>."
+            ).getBytes()
+        );
+        final TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setRDFHandler(rdfHandler);
+        parser.parse(bais, "http://test.base.uri");
+        final Statement statement = rdfHandler.getStatements().get(0);
+        Assert.assertEquals("http://www.v/dat/4b2-21", statement.getSubject().stringValue());
+        Assert.assertEquals("http://www.w3.org/20/ica#dtend", statement.getPredicate().stringValue());
+        Assert.assertTrue(statement.getObject() instanceof Literal);
+        Literal object = (Literal) statement.getObject();
+        Assert.assertEquals("2010", object.stringValue());
+        Assert.assertNull(object.getLanguage());
+        Assert.assertEquals("http://www.w3.org/2001/XMLSchema#integer", object.getDatatype().toString());
+        Assert.assertEquals("http://sin.siteserv.org/def/", statement.getContext().stringValue());
+    }
+
+    /**
+     * Tests the correct support for literal escaping.
+     *
+     * @throws RDFHandlerException
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    @Test
+    public void testLiteralEscapeManagement1()
+    throws RDFHandlerException, IOException, RDFParseException {
+        TestParseLocationListener parseLocationListener = new TestParseLocationListener();
+        TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setParseLocationListener(parseLocationListener);
+        parser.setRDFHandler(rdfHandler);
+
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+            "<http://a> <http://b> \"\\\\\" <http://c> .".getBytes()
+        );
+        parser.parse(bais, "http://base-uri");
+
+        rdfHandler.assertHandler(1);
+        parseLocationListener.assertListener(1, 40);
+    }
+
+    /**
+     * Tests the correct support for literal escaping.
+     *
+     * @throws RDFHandlerException
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    @Test
+    public void testLiteralEscapeManagement2()
+    throws RDFHandlerException, IOException, RDFParseException {
+        TestParseLocationListener parseLocationListener = new TestParseLocationListener();
+        TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setParseLocationListener(parseLocationListener);
+        parser.setRDFHandler(rdfHandler);
+
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+            "<http://a> <http://b> \"Line text 1\\nLine text 2\" <http://c> .".getBytes()
+        );
+        parser.parse(bais, "http://base-uri");
+
+        rdfHandler.assertHandler(1);
+        final Value object = rdfHandler.getStatements().get(0).getObject();
+        Assert.assertTrue( object instanceof Literal);
+        final String literalContent = ((Literal) object).getLabel();
+        Assert.assertEquals("Line text 1\nLine text 2", literalContent);
+    }
+
+    /**
+     * Tests the correct decoding of UTF-8 encoded chars in URIs.
+     *
+     * @throws RDFHandlerException
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    @Test
+    public void testURIDecodingManagement() throws RDFHandlerException, IOException, RDFParseException {
+        TestParseLocationListener parseLocationListener = new TestParseLocationListener();
+        TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setParseLocationListener(parseLocationListener);
+        parser.setRDFHandler(rdfHandler);
+
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+            "<http://s/\\u306F\\u3080> <http://p/\\u306F\\u3080> <http://o/\\u306F\\u3080> <http://g/\\u306F\\u3080> ."
+            .getBytes()
+        );
+        parser.parse(bais, "http://base-uri");
+
+        rdfHandler.assertHandler(1);
+        final Statement statement = rdfHandler.getStatements().get(0);
+
+        final Resource subject = statement.getSubject();
+        Assert.assertTrue( subject instanceof URI);
+        final String subjectURI = subject.toString();
+        Assert.assertEquals("http://s/はむ", subjectURI);
+
+        final Resource predicate = statement.getPredicate();
+        Assert.assertTrue( predicate instanceof URI);
+        final String predicateURI = predicate.toString();
+        Assert.assertEquals("http://p/はむ", predicateURI);
+
+        final Value object = statement.getObject();
+        Assert.assertTrue( object instanceof URI);
+        final String objectURI = object.toString();
+        Assert.assertEquals("http://o/はむ", objectURI);
+
+        final Resource graph = statement.getContext();
+        Assert.assertTrue( graph instanceof URI);
+        final String graphURI = graph.toString();
+        Assert.assertEquals("http://g/はむ", graphURI);
+    }
+
+    @Test
+    public void testUnicodeLiteralManagement() throws RDFHandlerException, IOException, RDFParseException {
+        TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setRDFHandler(rdfHandler);
+        final String INPUT_LITERAL = "[は、イギリスおよびイングランドの首都である] [是大不列顛及北愛爾蘭聯合王國和英格蘭的首都]";
+        final String INPUT_STRING = String.format(
+                "<http://a> <http://b> \"%s\" <http://c> .",
+                INPUT_LITERAL
+        );
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+            INPUT_STRING.getBytes()
+        );
+        parser.parse(bais, "http://base-uri");
+
+        rdfHandler.assertHandler(1);
+        final Literal obj = (Literal) rdfHandler.getStatements().get(0).getObject();
+        Assert.assertEquals(INPUT_LITERAL, obj.getLabel());
+    }
+
+    @Test
+    public void testUnicodeLiteralDecoding() throws RDFHandlerException, IOException, RDFParseException {
+        TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setRDFHandler(rdfHandler);
+        final String INPUT_LITERAL_PLAIN   = "[は]";
+        final String INPUT_LITERAL_ENCODED = "[\\u306F]";
+        final String INPUT_STRING = String.format(
+                "<http://a> <http://b> \"%s\" <http://c> .",
+                INPUT_LITERAL_ENCODED
+        );
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+            INPUT_STRING.getBytes()
+        );
+        parser.parse(bais, "http://base-uri");
+
+        rdfHandler.assertHandler(1);
+        final Literal obj = (Literal) rdfHandler.getStatements().get(0).getObject();
+        Assert.assertEquals(INPUT_LITERAL_PLAIN, obj.getLabel());
+    }
+
+    @Test(expected = RDFParseException.class)
+    public void testWrongUnicodeEncodedCharFail() throws RDFHandlerException, IOException, RDFParseException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+                "<http://s> <http://p> \"\\u123X\" <http://g> .".getBytes()
+        );
+        parser.parse(bais, "http://base-uri");
+    }
+
+    /**
+     * Tests the correct support for EOS exception.
+     *
+     * @throws RDFHandlerException
+     * @throws IOException
+     * @throws RDFParseException
+     */
+    @Test(expected = RDFParseException.class)
+    public void testEndOfStreamReached()
+    throws RDFHandlerException, IOException, RDFParseException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+            "<http://a> <http://b> \"\\\" <http://c> .".getBytes()
+        );
+        parser.parse(bais, "http://base-uri");
+    }
+
+    /**
+     * Tests the parser with all cases defined by the NQuads grammar.
+     *
+     * @throws IOException
+     * @throws RDFParseException
+     * @throws RDFHandlerException
+     */
+    @Test
+    public void testFullParseScenario()
+    throws IOException, RDFParseException, RDFHandlerException {
+        TestParseLocationListener parseLocationListerner = new TestParseLocationListener();
+        FullParseScenarioRDFHandler rdfHandler = new FullParseScenarioRDFHandler();
+        parser.setParseLocationListener(parseLocationListerner);
+        parser.setRDFHandler(rdfHandler);
+
+        BufferedReader br = new BufferedReader(
+                new InputStreamReader(
+                        this.getClass().getClassLoader().getResourceAsStream("application/nquads/test1.nq")
+                ) 
+        );
+        parser.parse(
+            br,
+            "http://test.base.uri"
+        );
+
+        rdfHandler.assertHandler(6);
+        parseLocationListerner.assertListener(8, 71);
+    }
+
+    /**
+     * Tests parser with real data.
+     *
+     * @throws IOException
+     * @throws RDFParseException
+     * @throws RDFHandlerException
+     */
+    @Test
+    public void testParseRealData()
+    throws IOException, RDFParseException, RDFHandlerException {
+        TestParseLocationListener parseLocationListener = new TestParseLocationListener();
+        TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setParseLocationListener(parseLocationListener);
+        parser.setRDFHandler(rdfHandler);
+
+        parser.parse(
+            this.getClass().getClassLoader().getResourceAsStream("application/nquads/test2.nq"),
+            "http://test.base.uri"
+        );
+
+        rdfHandler.assertHandler(400);
+        parseLocationListener.assertListener(400, 349);
+    }
+
+    @Test
+    public void testStatementWithInvalidLiteralContentAndIgnoreValidation()
+    throws RDFHandlerException, IOException, RDFParseException {
+        verifyStatementWithInvalidLiteralContent(RDFParser.DatatypeHandling.IGNORE);
+    }
+
+    @Test(expected = RDFParseException.class)
+    public void testStatementWithInvalidLiteralContentAndStrictValidation()
+    throws RDFHandlerException, IOException, RDFParseException {
+        verifyStatementWithInvalidLiteralContent(RDFParser.DatatypeHandling.VERIFY);
+    }
+
+    @Test
+    public void testStatementWithInvalidDatatypeAndIgnoreValidation()
+    throws RDFHandlerException, IOException, RDFParseException {
+        verifyStatementWithInvalidDatatype(RDFParser.DatatypeHandling.IGNORE);
+    }
+
+    @Test
+    public void testStatementWithInvalidDatatypeAndVerifyValidation()
+    throws RDFHandlerException, IOException, RDFParseException {
+        verifyStatementWithInvalidDatatype(RDFParser.DatatypeHandling.VERIFY);
+    }
+
+    @Test (expected = RDFParseException.class)
+    public void testStopAtFirstErrorStrictParsing() throws RDFHandlerException, IOException, RDFParseException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+                (
+                    "<http://s0> <http://p0> <http://o0> <http://g0> .\n" +
+                    "<http://sX>                                     .\n" + // Line with error.
+                    "<http://s1> <http://p1> <http://o1> <http://g1> .\n"
+                ).getBytes()
+        );
+        parser.setStopAtFirstError(true);
+        parser.parse(bais, "http://base-uri");
+    }
+
+    @Test
+    public void testStopAtFirstErrorTolerantParsing() throws RDFHandlerException, IOException, RDFParseException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+                (
+                    "<http://s0> <http://p0> <http://o0> <http://g0> .\n" +
+                    "<http://sX>                                     .\n" + // Line with error.
+                    "<http://s1> <http://p1> <http://o1> <http://g1> .\n"
+                ).getBytes()
+        );
+        final TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setRDFHandler(rdfHandler);
+        parser.setStopAtFirstError(false);
+        parser.parse(bais, "http://base-uri");
+        rdfHandler.assertHandler(2);
+        final List<Statement> statements = rdfHandler.getStatements();
+        final int size = statements.size();
+        for(int i = 0; i < size; i++) {
+            Assert.assertEquals("http://s" + i, statements.get(i).getSubject().stringValue()  );
+            Assert.assertEquals("http://p" + i, statements.get(i).getPredicate().stringValue());
+            Assert.assertEquals("http://o" + i, statements.get(i).getObject().stringValue()   );
+            Assert.assertEquals("http://g" + i, statements.get(i).getContext().stringValue()  );
+        }
+    }
+
+    @Test
+    public void testReportInvalidLiteralAttribute() throws RDFHandlerException, IOException, RDFParseException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+                "<http://a> <http://b> \"literal\"^^xsd:datetime <http://c> .".getBytes()
+        );
+        try {
+            parser.parse(bais, "http://base-uri");
+            Assert.fail("Expected failure here.");
+        } catch (RDFParseException e) {
+            Assert.assertTrue(e.getMessage().contains("expected '<'"));
+            Assert.assertEquals(1 , e.getLineNumber());
+            Assert.assertEquals(35, e.getColumnNumber());
+        }
+    }
+
+    @Test
+    public void testParseWithNoContext() throws RDFHandlerException, IOException, RDFParseException {
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+            ("<http://www.v/dat/4b2-21>" +
+             "<http://www.w3.org/20/ica#dtend>" +
+             "\"2010\"^^<http://www.w3.org/2001/XMLSchema#integer> ."
+            ).getBytes()
+        );
+        final TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setRDFHandler(rdfHandler);
+        parser.parse(bais, "http://test.base.uri");
+        final Statement statement = rdfHandler.getStatements().get(0);
+        Assert.assertEquals("http://www.v/dat/4b2-21", statement.getSubject().stringValue());
+        Assert.assertEquals("http://www.w3.org/20/ica#dtend", statement.getPredicate().stringValue());
+        Assert.assertTrue(statement.getObject() instanceof Literal);
+        Literal object = (Literal) statement.getObject();
+        Assert.assertEquals("2010", object.stringValue());
+        Assert.assertNull(object.getLanguage());
+        Assert.assertEquals("http://www.w3.org/2001/XMLSchema#integer", object.getDatatype().toString());
+        Assert.assertNull(statement.getContext());
+    }
+
+    private void verifyStatementWithInvalidLiteralContent(RDFParser.DatatypeHandling datatypeHandling)
+    throws RDFHandlerException, IOException, RDFParseException {
+       final ByteArrayInputStream bais = new ByteArrayInputStream(
+                (
+                "<http://dbpedia.org/resource/Camillo_Benso,_conte_di_Cavour> " +
+                "<http://dbpedia.org/property/mandatofine> " +
+                "\"1380.0\"^^<http://www.w3.org/2001/XMLSchema#int> " + // Float declared as int.
+                "<http://it.wikipedia.org/wiki/Camillo_Benso,_conte_di_Cavour#absolute-line=20> ."
+                ).getBytes()
+        );
+        parser.setDatatypeHandling(datatypeHandling);
+        parser.parse(bais, "http://base-uri");
+    }
+
+    private void verifyStatementWithInvalidDatatype(RDFParser.DatatypeHandling datatypeHandling)
+    throws RDFHandlerException, IOException, RDFParseException {
+        TestRDFHandler rdfHandler = new TestRDFHandler();
+        parser.setRDFHandler(rdfHandler);
+        parser.setDatatypeHandling(datatypeHandling);
+        final ByteArrayInputStream bais = new ByteArrayInputStream(
+                (
+                        "<http://dbpedia.org/resource/Camillo_Benso,_conte_di_Cavour> " +
+                        "<http://dbpedia.org/property/mandatofine> " +
+                        "\"1380.0\"^^<http://dbpedia.org/datatype/second> " +
+                        "<http://it.wikipedia.org/wiki/Camillo_Benso,_conte_di_Cavour#absolute-line=20> ."
+                ).getBytes()
+        );
+        parser.parse(bais, "http://base-uri");
+        rdfHandler.assertHandler(1);
+    }
+
+    private class TestParseLocationListener implements ParseLocationListener {
+
+        private int lastRow, lastCol;
+
+        public void parseLocationUpdate(int r, int c) {
+            lastRow = r;
+            lastCol = c;
+        }
+
+        private void assertListener(int row, int col) {
+            Assert.assertEquals("Unexpected last row", row , lastRow);
+            Assert.assertEquals("Unexpected last col", col , lastCol);
+        }
+
+    }
+
+    private class TestRDFHandler implements RDFHandler {
+
+        private boolean started = false;
+        private boolean ended   = false;
+
+        private final List<Statement> statements = new ArrayList<Statement>();
+
+        protected List<Statement> getStatements() {
+            return statements;
+        }
+
+        public void startRDF() throws RDFHandlerException {
+            started = true;
+        }
+
+        public void endRDF() throws RDFHandlerException {
+            ended = true;
+        }
+
+        public void handleNamespace(String s, String s1) throws RDFHandlerException {
+            throw new UnsupportedOperationException();
+        }
+
+        public void handleStatement(Statement statement) throws RDFHandlerException {
+            logger.debug(statement.toString());
+            statements.add(statement);
+        }
+
+        public void handleComment(String s) throws RDFHandlerException {
+            throw new UnsupportedOperationException();
+        }
+
+        public void assertHandler(int expected) {
+            Assert.assertTrue("Never stated.", started);
+            Assert.assertTrue("Never ended." , ended  );
+            Assert.assertEquals("Unexpected number of statements.", expected, statements.size());
+        }
+    }
+
+    private class FullParseScenarioRDFHandler extends TestRDFHandler {
+
+        public void handleStatement(Statement statement) throws RDFHandlerException {
+            int statementIndex = getStatements().size();
+            if(statementIndex == 0){
+                Assert.assertEquals(new URIImpl("http://example.org/alice/foaf.rdf#me"), statement.getSubject() );
+            } else {
+                Assert.assertTrue(statement.getSubject() instanceof BNode);
+            }
+
+            if( statementIndex == 4) {
+                Assert.assertEquals(new URIImpl("http://test.base.uri#like"), statement.getPredicate() );
+            }
+
+            if(statementIndex == 5) {
+                Assert.assertNull(statement.getContext());
+            } else {
+                Assert.assertEquals(
+                        new URIImpl(String.format("http://example.org/alice/foaf%s.rdf", statementIndex + 1)),
+                        statement.getContext()
+                );
+            }
+
+            super.handleStatement(statement);
+        }
+    }
+
+}
\ No newline at end of file

Added: incubator/any23/trunk/nquads/src/test/java/org/apache/any23/io/nquads/NQuadsWriterTest.java
URL: http://svn.apache.org/viewvc/incubator/any23/trunk/nquads/src/test/java/org/apache/any23/io/nquads/NQuadsWriterTest.java?rev=1380396&view=auto
==============================================================================
--- incubator/any23/trunk/nquads/src/test/java/org/apache/any23/io/nquads/NQuadsWriterTest.java (added)
+++ incubator/any23/trunk/nquads/src/test/java/org/apache/any23/io/nquads/NQuadsWriterTest.java Mon Sep  3 23:03:29 2012
@@ -0,0 +1,176 @@
+/*
+ * 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.any23.io.nquads;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.openrdf.model.BNode;
+import org.openrdf.model.Literal;
+import org.openrdf.model.Resource;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.Value;
+import org.openrdf.model.ValueFactory;
+import org.openrdf.model.impl.ValueFactoryImpl;
+import org.openrdf.rio.RDFHandlerException;
+import org.openrdf.rio.RDFParseException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Test case for {@link NQuadsWriter}.
+ *
+ * @author Michele Mostarda (mostarda@fbk.eu)
+ */
+public class NQuadsWriterTest {
+
+    private static final Logger logger  = LoggerFactory.getLogger(NQuadsWriterTest.class);
+
+    private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+    private NQuadsWriter writer;
+
+    private ValueFactory vf;
+    
+    @Before
+    public void setUp() {
+        vf = ValueFactoryImpl.getInstance();
+        writer = new NQuadsWriter(baos);
+    }
+
+    @After
+    public void tearDown() {
+        logger.debug( "\n" + baos.toString() );
+        baos.reset();
+        writer = null;
+    }
+
+    @Test
+    public void testWrite() throws RDFHandlerException {
+        Statement s1 = quad(
+                uri("http://sub"),
+                uri("http://pre"),
+                uri("http://obj"),
+                uri("http://gra1")
+        );
+        Statement s2 = quad(
+                bnode("1"),
+                uri("http://pre"),
+                bnode("2"),
+                uri("http://gra2")
+        );
+        Statement s3 = quad(
+                bnode("3"),
+                uri("http://pre"),
+                literal("Sample text 1"),
+                uri("http://gra2")
+        );
+        Statement s4 = quad(
+                bnode("4"),
+                uri("http://pre"),
+                literal("Sample text 2", "en"),
+                uri("http://gra2")
+        );
+        Statement s5 = quad(
+                bnode("5"),
+                uri("http://pre"),
+                literal("12345", uri("http://www.w3.org/2001/XMLSchema#integer")),
+                uri("http://gra2")
+        );
+        Statement s6 = quad(
+                uri("p1:sub"),
+                uri("p1:pre"),
+                uri("p1:obj"),
+                uri("p1:gra2")
+        );
+        Statement s7 = quad(
+                uri("http://sub"),
+                uri("http://pre"),
+                literal("This is line 1.\nThis is line 2.\n"),
+                uri("http://gra3")
+        );
+
+        // Sending events.
+        writer.startRDF();
+        writer.handleNamespace("p1", "http://test.com/");
+        writer.handleStatement(s1);
+        writer.handleStatement(s2);
+        writer.handleStatement(s3);
+        writer.handleStatement(s4);
+        writer.handleStatement(s5);
+        writer.handleStatement(s6);
+        writer.handleStatement(s7);
+        writer.endRDF();
+
+        // Checking content.
+        String content = baos.toString();
+        String[] lines = content.split("\n");
+        Assert.assertEquals("Unexpected number of lines.", 7, lines.length);
+        Assert.assertTrue( lines[0].matches("<.*> <.*> <.*> <.*> \\.") );
+        Assert.assertTrue( lines[1].matches("_:.* <.*> _:.* <.*> \\.") );
+        Assert.assertTrue( lines[2].matches("_:.* <.*> \".*\" <.*> \\.") );
+        Assert.assertTrue( lines[3].matches("_:.* <.*> \".*\"@en <.*> \\.") );
+        Assert.assertTrue( lines[4].matches("_:.* <.*> \".*\"\\^\\^<.*> <.*> \\.") );
+        Assert.assertTrue( lines[5].matches("<http://.*> <http://.*> <http://.*> <http://.*> \\.") );
+        Assert.assertEquals(
+                "<http://sub> <http://pre> \"This is line 1.\\nThis is line 2.\\n\" <http://gra3> .",
+                lines[6]
+        );
+    }
+
+    @Test
+    public void testReadWrite() throws RDFHandlerException, IOException, RDFParseException {
+        NQuadsParser parser = new NQuadsParser();
+        parser.setRDFHandler(writer);
+        parser.parse(
+            this.getClass().getClassLoader().getResourceAsStream("application/nquads/test2.nq"),
+            "http://test.base.uri"
+        );
+
+        Assert.assertEquals("Unexpected number of lines.", 400, baos.toString().split("\n").length);
+    }
+    
+    private Statement quad(Resource subject, URI predicate, Value object, Resource context) {
+        return this.vf.createStatement(subject, predicate, object, context);
+    }
+
+    private URI uri(String uri) {
+        return this.vf.createURI(uri);
+    }
+
+    private BNode bnode(String testID) {
+        return this.vf.createBNode(testID);
+    }
+
+    private Literal literal(String literalValue) {
+        return this.vf.createLiteral(literalValue);
+    }
+
+    private Literal literal(String literalValue, URI datatype) {
+        return this.vf.createLiteral(literalValue, datatype);
+    }
+
+    private Literal literal(String literalValue, String language) {
+        return this.vf.createLiteral(literalValue, language);
+    }
+}

Modified: incubator/any23/trunk/pom.xml
URL: http://svn.apache.org/viewvc/incubator/any23/trunk/pom.xml?rev=1380396&r1=1380395&r2=1380396&view=diff
==============================================================================
--- incubator/any23/trunk/pom.xml (original)
+++ incubator/any23/trunk/pom.xml Mon Sep  3 23:03:29 2012
@@ -190,6 +190,9 @@
   <modules>
     <module>api</module>
     <module>test-resources</module>
+    <module>nquads</module>
+    <module>csvutils</module>
+    <module>mime</module>
     <module>core</module>
     <module>plugins/basic-crawler</module>
     <module>plugins/html-scraper</module>
@@ -332,6 +335,11 @@
       </dependency>
       <dependency>
         <groupId>org.openrdf.sesame</groupId>
+        <artifactId>sesame-rio-n3</artifactId>
+        <version>${sesame.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.openrdf.sesame</groupId>
         <artifactId>sesame-rio-trix</artifactId>
         <version>${sesame.version}</version>
       </dependency>
@@ -387,13 +395,18 @@
       </dependency>
       <!-- END: Sesame -->
 
-      <!-- BEGIN:  Apache Commons  CSV-->
+      <!-- BEGIN:  Apache Commons -->
       <dependency>
         <groupId>org.apache.commons</groupId>
         <artifactId>commons-csv</artifactId>
         <version>1.0-SNAPSHOT-rev1148315</version>
       </dependency>
-      <!-- END:  Apache Commons CSV -->
+      <dependency>
+        <groupId>commons-io</groupId>
+        <artifactId>commons-io</artifactId>
+        <version>2.4</version>
+      </dependency>
+      <!-- END:  Apache Commons -->
 
       <!-- BEGIN: Servlet Deps. -->
       <dependency>
@@ -439,6 +452,11 @@
         <artifactId>jcl-over-slf4j</artifactId>
         <version>${slf4j.logger.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.slf4j</groupId>
+        <artifactId>slf4j-log4j12</artifactId>
+        <version>${slf4j.logger.version}</version>
+      </dependency>
       <!-- END: logger -->
 
       <!-- BEGIN: plugins -->



Mime
View raw message