reset json writer
authorJulio Caguano <julio.caguanob@gmail.com>
Sun, 6 May 2018 20:45:55 +0000 (15:45 -0500)
committerJulio Caguano <julio.caguanob@gmail.com>
Sun, 6 May 2018 20:45:55 +0000 (15:45 -0500)
core/src/main/java/org/apache/any23/writer/JSONWriter.java
core/src/test/java/org/apache/any23/writer/JSONWriterTest.java
service/src/test/java/org/apache/any23/servlet/ServletTest.java

index 567c014..a4cce5a 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.any23.writer;
 
+import java.io.BufferedOutputStream;
 import java.io.OutputStream;
-import org.eclipse.rdf4j.rio.RDFFormat;
-import org.eclipse.rdf4j.rio.Rio;
+import java.io.PrintStream;
+import java.util.Optional;
+import org.apache.any23.extractor.ExtractionContext;
+import org.eclipse.rdf4j.model.BNode;
+import org.eclipse.rdf4j.model.IRI;
+import org.eclipse.rdf4j.model.Literal;
+import org.eclipse.rdf4j.model.Resource;
+import org.eclipse.rdf4j.model.Value;
 
 /**
  * Implementation of <i>JSON</i> format writer.
  *
  * @author Michele Mostarda (mostarda@fbk.eu)
  */
-public class JSONWriter extends RDFWriterTripleHandler implements FormatWriter {
+public class JSONWriter implements FormatWriter {
+
+    private final PrintStream ps;
+
+    private boolean documentStarted = false;
+
+    private boolean firstArrayElemWritten = false;
+    private boolean firstObjectWritten    = false;
 
     public JSONWriter(OutputStream os) {
-        super(Rio.createWriter(RDFFormat.JSONLD, os));
+        if(os == null) {
+            throw new NullPointerException("Output stream cannot be null.");
+        }
+        this.ps = new PrintStream(new BufferedOutputStream(os));
+    }
+
+    @Override
+    public void startDocument(IRI documentIRI) throws TripleHandlerException {
+        if(documentStarted) {
+            throw new IllegalStateException("Document already started.");
+        }
+        documentStarted = true;
+
+        firstArrayElemWritten = false;
+        ps.print("{ \"quads\" : [");
+    }
+
+    @Override
+    public void openContext(ExtractionContext context) throws TripleHandlerException {
+        // Empty.
+    }
+
+    @Override
+    public void receiveTriple(Resource s, IRI p, Value o, IRI g, ExtractionContext context)
+    throws TripleHandlerException {
+        validateDocumentStarted();
+
+        if(firstArrayElemWritten) {
+            ps.print(", ");
+        } else {
+            firstArrayElemWritten = true;
+        }
+        firstObjectWritten    = false;
+        
+        ps.print('[');
+
+        if(s instanceof IRI) {
+            printExplicitIRI(s.stringValue(), ps);
+        } else {
+            printBNode(s.stringValue(), ps);
+        }
+
+        printIRI(p.stringValue(), ps);
+
+         if(o instanceof IRI) {
+            printExplicitIRI(o.stringValue(), ps);
+        } else if(o instanceof BNode) {
+            printBNode(o.stringValue(), ps);
+        } else {
+            printLiteral((Literal) o, ps);
+        }
+
+        printIRI(g == null ? null : g.stringValue(), ps);
+
+        ps.print(']');
+    }
+
+    @Override
+    public void receiveNamespace(String prefix, String uri, ExtractionContext context)
+    throws TripleHandlerException {
+        // Empty.
+    }
+
+    @Override
+    public void closeContext(ExtractionContext context) throws TripleHandlerException {
+        // Empty.
+    }
+
+    @Override
+    public void endDocument(IRI documentIRI) throws TripleHandlerException {
+        validateDocumentStarted();
+        ps.print("]}");
+        documentStarted = false;
+    }
+
+    @Override
+    public void setContentLength(long contentLength) {
+        // Empty.
+    }
+
+    @Override
+    public void close() throws TripleHandlerException {
+       if(documentStarted) {
+               endDocument(null);
+       }
+        ps.close();
+    }
+
+    private void validateDocumentStarted() {
+       if(!documentStarted) {
+            throw new IllegalStateException("Document didn't start.");
+        }
+    }
+
+    private void printIRI(String uri, PrintStream ps) {
+        printValue(uri, ps);
+    }
+
+    private void printExplicitIRI(String uri, PrintStream ps) {
+        printValue("uri", uri, ps);
+    }
+
+    private void printBNode(String bnode, PrintStream ps) {
+        printValue("bnode", bnode, ps);
+    }
+
+    private void printCommaIfNeeded(PrintStream ps) {
+        if(firstObjectWritten) {
+            ps.print(", ");
+        } else {
+            firstObjectWritten = true;
+        }
+    }
+
+    private void printLiteral(Literal literal, PrintStream ps) {
+        printCommaIfNeeded(ps);
+
+        ps.print('{');
+
+        ps.print("\"type\" : \"literal\"");
+
+        ps.print(", ");
+
+        ps.print("\"value\" : ");
+        ps.print('"');
+        ps.print(literal.stringValue());
+        ps.print('"');
+
+        ps.print(", ");
+
+        ps.print("\"lang\" : ");
+        final Optional<String> language = literal.getLanguage();
+        if (language.isPresent()) {
+            ps.print('"');
+            ps.print(literal.getLanguage().get());
+            ps.print('"');
+        } else {
+            ps.print("null");
+        }
+
+        ps.print(", ");
+
+        ps.print("\"datatype\" : ");
+        final IRI datatype = literal.getDatatype();
+        if(datatype != null) {
+        ps.print('"');
+        ps.print(datatype.stringValue());
+        ps.print('"');
+        } else {
+            ps.print("null");
+        }
+
+        ps.print('}');
+    }
+
+    private void printValue(String type, String value, PrintStream ps) {
+        printCommaIfNeeded(ps);
+
+        ps.print("{ \"type\" : \"");
+        ps.print(type);
+        ps.print("\", \"value\" : ");
+        if (value != null) {
+            ps.print('"');
+            ps.print(value);
+            ps.print('"');
+        } else {
+            ps.print("null");
+        }
+        ps.print('}');
+    }
+
+    private void printValue(String value, PrintStream ps) {
+        printCommaIfNeeded(ps);
+
+        if (value != null) {
+            ps.print('"');
+            ps.print(value);
+            ps.print('"');
+        } else {
+            ps.print("null");
+        }
+    }
+
+    @Override
+    public boolean isAnnotated() {
+        return false; // TODO: add annotation support.
+    }
+
+    @Override
+    public void setAnnotated(boolean f) {
+        // Empty.
     }
 }
index 1b1d846..44bb5c0 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.apache.any23.writer;
 
 import java.io.ByteArrayOutputStream;
-import org.apache.any23.extractor.ExtractionContext;
 import org.eclipse.rdf4j.model.IRI;
 import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
 import org.junit.Assert;
@@ -33,41 +33,57 @@ public class JSONWriterTest {
     @Test
     public void testWriting() throws TripleHandlerException {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        try (JSONWriter jsonWriter = new JSONWriter(baos);) {
-            final IRI documentIRI = SimpleValueFactory.getInstance().createIRI("http://fake/uri");
-            ExtractionContext extractionContext = new ExtractionContext("rdf-nq", SimpleValueFactory.getInstance().createIRI("http://any23.org/tmp/"));
-           
-            jsonWriter.startDocument(documentIRI);
-            jsonWriter.receiveTriple(
-                    SimpleValueFactory.getInstance().createBNode("bn1"),
-                    SimpleValueFactory.getInstance().createIRI("http://pred/1"),
-                    SimpleValueFactory.getInstance().createIRI("http://value/1"),
-                    SimpleValueFactory.getInstance().createIRI("http://graph/1"),
-                    null
-            );
-            jsonWriter.receiveTriple(
-                    SimpleValueFactory.getInstance().createIRI("http://sub/2"),
-                    SimpleValueFactory.getInstance().createIRI("http://pred/2"),
-                    SimpleValueFactory.getInstance().createLiteral("language literal", "en"),
-                    SimpleValueFactory.getInstance().createIRI("http://graph/2"),
-                    null
-            );
-            jsonWriter.receiveTriple(
-                    SimpleValueFactory.getInstance().createIRI("http://sub/3"),
-                    SimpleValueFactory.getInstance().createIRI("http://pred/3"),
-                    SimpleValueFactory.getInstance().createLiteral("123", SimpleValueFactory.getInstance().createIRI("http://datatype")),
-                    null,
-                    extractionContext
-            );
-            jsonWriter.endDocument(documentIRI);
+        try(JSONWriter jsonWriter = new JSONWriter(baos);) {
+               final IRI documentIRI = SimpleValueFactory.getInstance().createIRI("http://fake/uri");
+               jsonWriter.startDocument(documentIRI);
+               jsonWriter.receiveTriple(
+                       SimpleValueFactory.getInstance().createBNode("bn1"),
+                       SimpleValueFactory.getInstance().createIRI("http://pred/1"),
+                       SimpleValueFactory.getInstance().createIRI("http://value/1"),
+                       SimpleValueFactory.getInstance().createIRI("http://graph/1"),
+                       null
+               );
+               jsonWriter.receiveTriple(
+                       SimpleValueFactory.getInstance().createIRI("http://sub/2"),
+                       SimpleValueFactory.getInstance().createIRI("http://pred/2"),
+                       SimpleValueFactory.getInstance().createLiteral("language literal", "en"),
+                       SimpleValueFactory.getInstance().createIRI("http://graph/2"),
+                       null
+               );
+               jsonWriter.receiveTriple(
+                       SimpleValueFactory.getInstance().createIRI("http://sub/3"),
+                       SimpleValueFactory.getInstance().createIRI("http://pred/3"),
+                       SimpleValueFactory.getInstance().createLiteral("123", SimpleValueFactory.getInstance().createIRI("http://datatype")),
+                       null,
+                       null
+               );
+               jsonWriter.endDocument(documentIRI);
         }
 
-        final String expected
-                = "["
-                + "{\"@graph\":[{\"@id\":\"http://sub/3\",\"http://pred/3\":[{\"@type\":\"http://datatype\",\"@value\":\"123\"}]}],\"@id\":\"http://any23.org/tmp/\"},"
-                + "{\"@graph\":[{\"@id\":\"_:bn1\",\"http://pred/1\":[{\"@id\":\"http://value/1\"}]}],\"@id\":\"http://graph/1\"},"
-                + "{\"@graph\":[{\"@id\":\"http://sub/2\",\"http://pred/2\":[{\"@language\":\"en\",\"@value\":\"language literal\"}]}],\"@id\":\"http://graph/2\"}"
-                + "]";
+        final String expected =
+            "{ " +
+            "\"quads\" : " +
+            "[" +
+            "[" +
+            "{ \"type\" : \"bnode\", \"value\" : \"bn1\"}, " +
+            "\"http://pred/1\", " +
+            "{ \"type\" : \"uri\", \"value\" : \"http://value/1\"}, " +
+            "\"http://graph/1\"" +
+            "], " +
+            "[" +
+            "{ \"type\" : \"uri\", \"value\" : \"http://sub/2\"}, " +
+            "\"http://pred/2\", " +
+            "{\"type\" : \"literal\", \"value\" : \"language literal\", \"lang\" : \"en\", \"datatype\" : \"http://www.w3.org/1999/02/22-rdf-syntax-ns#langString\"}, " +
+            "\"http://graph/2\"" +
+            "], " +
+            "[" +
+            "{ \"type\" : \"uri\", \"value\" : \"http://sub/3\"}, " +
+            "\"http://pred/3\", " +
+            "{\"type\" : \"literal\", \"value\" : \"123\", \"lang\" : null, \"datatype\" : \"http://datatype\"}, " +
+            "null" +
+            "]" +
+            "]" +
+            "}";
         Assert.assertEquals(expected, baos.toString());
     }
 }
index 02c0603..2359e90 100644 (file)
@@ -14,7 +14,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.apache.any23.servlet;
 
 import java.io.File;
@@ -223,7 +222,9 @@ public class ServletTest {
     }
 
     /**
-     * This test has been disabled in order to avoid external resources dependencies
+     * This test has been disabled in order to avoid external resources
+     * dependencies
+     *
      * @throws Exception
      */
     @Test
@@ -233,8 +234,10 @@ public class ServletTest {
         Assert.assertEquals(200, response.getStatus());
     }
 
-     /**
-     * This test has been disabled in order to avoid external resources dependencies
+    /**
+     * This test has been disabled in order to avoid external resources
+     * dependencies
+     *
      * @throws Exception
      */
     @Test
@@ -244,8 +247,10 @@ public class ServletTest {
         Assert.assertEquals(200, response.getStatus());
     }
 
-     /**
-     * This test has been disabled in order to avoid external resources dependencies
+    /**
+     * This test has been disabled in order to avoid external resources
+     * dependencies
+     *
      * @throws Exception
      */
     @Test
@@ -375,16 +380,16 @@ public class ServletTest {
         HttpTester response = doGetRequest("/best/http://foo.com?validation-mode=validate-fix&report=on");
         Assert.assertEquals(200, response.getStatus());
         final String content = response.getContent();
-        assertContainsTag("response"        , content);
-        assertContainsTag("extractors"      , content);
-        assertContainsTag("report"          , content);
-        assertContainsTag("message", true, 1 , content);
-        assertContainsTag("error"  , true, 1 , content);
-        assertContainsTag("error"  , true, 1 , content);
+        assertContainsTag("response", content);
+        assertContainsTag("extractors", content);
+        assertContainsTag("report", content);
+        assertContainsTag("message", true, 1, content);
+        assertContainsTag("error", true, 1, content);
+        assertContainsTag("error", true, 1, content);
         assertContainsTag("validationReport", content);
-        assertContainsTag("errors"          , content);
-        assertContainsTag("issues"          , content);
-        assertContainsTag("ruleActivations" , content);
+        assertContainsTag("errors", content);
+        assertContainsTag("issues", content);
+        assertContainsTag("ruleActivations", content);
         assertContainsTag("data", content);
     }
 
@@ -393,13 +398,13 @@ public class ServletTest {
         String body = "<http://sub/1> <http://pred/1> \"123\"^^<http://datatype> <http://graph/1>.";
         HttpTester response = doPostRequest("/json", body, "application/n-quads");
         Assert.assertEquals(200, response.getStatus());
-        final String EXPECTED_JSON =
+        final String EXPECTED_JSON = 
                 "["
-                + "{\"@graph\":"
-                + "["
-                + "{\"@id\":\"http://sub/1\","
-                + "\"http://pred/1\":[{\"@type\":\"http://datatype\",\"@value\":\"123\"}]}],"
-                + "\"@id\":\"http://graph/1\"}]";
+                + "{ \"type\" : \"uri\", \"value\" : \"http://sub/1\"}, "
+                + "\"http://pred/1\", "
+                + "{\"type\" : \"literal\", \"value\" : \"123\", \"lang\" : null, \"datatype\" : \"http://datatype\"}, "
+                + "\"http://graph/1\""
+                + "]";
         assertContains(EXPECTED_JSON, response.getContent());
     }
 
@@ -409,8 +414,8 @@ public class ServletTest {
         HttpTester response = doPostRequest("/trix", body, "application/n-quads");
         Assert.assertEquals(200, response.getStatus());
         final String content = response.getContent();
-        assertContainsTag("graph" , false, 1, content);
-        assertContainsTag("uri"   , false, 3, content);
+        assertContainsTag("graph", false, 1, content);
+        assertContainsTag("uri", false, 3, content);
         assertContainsTag("triple", false, 1, content);
     }
 
@@ -451,9 +456,12 @@ public class ServletTest {
     }
 
     private void assertContains(String expected, String container) {
-        if(expected.length() == 0)
+        if (expected.length() == 0) {
             throw new IllegalArgumentException("expected string must contains at lease one char.");
-        if (container.contains(expected)) return;
+        }
+        if (container.contains(expected)) {
+            return;
+        }
         Assert.fail("expected '" + expected + "' to be contained in '" + container + "'");
     }
 
@@ -468,8 +476,8 @@ public class ServletTest {
             Assert.assertEquals(
                     String.format("Cannot find open tag %s %d times", tag, occurrences),
                     occurrences,
-                    StringUtils.countOccurrences(container, "<" + tag + ">") +
-                    StringUtils.countOccurrences(container, "<" + tag + " ")
+                    StringUtils.countOccurrences(container, "<" + tag + ">")
+                    StringUtils.countOccurrences(container, "<" + tag + " ")
             );
             Assert.assertEquals(
                     String.format("Cannot find close tag %s %d times", tag, occurrences),
@@ -492,7 +500,7 @@ public class ServletTest {
         protected DocumentSource createHTTPDocumentSource(HTTPClient httpClient, String uri)
                 throws IOException, URISyntaxException {
             requestedIRI = uri;
-            if(content != null) {
+            if (content != null) {
                 return new StringDocumentSource(content, uri);
             } else {
                 return super.createHTTPDocumentSource(httpClient, uri);