You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2013/01/19 15:52:57 UTC

svn commit: r1435565 - in /jena/Experimental/riot-output: ./ src/main/java/dev/ src/main/java/out/ src/main/java/riot/ src/main/java/riot/other/ src/main/java/riot/out/ src/main/java/riot/writer/

Author: andy
Date: Sat Jan 19 14:52:56 2013
New Revision: 1435565

URL: http://svn.apache.org/viewvc?rev=1435565&view=rev
Log:
New Turtle/TriG writer.

Added:
    jena/Experimental/riot-output/D.trig
    jena/Experimental/riot-output/W.trig
      - copied unchanged from r1422691, jena/Scratch/AFS/Dev/trunk/D.trig
    jena/Experimental/riot-output/W.ttl
      - copied unchanged from r1432476, jena/Scratch/AFS/Dev/trunk/D.ttl
    jena/Experimental/riot-output/src/main/java/dev/MainOutput.java
      - copied, changed from r1435266, jena/Experimental/riot-output/src/main/java/dev/OutputMain.java
    jena/Experimental/riot-output/src/main/java/dev/MainWriter.java
    jena/Experimental/riot-output/src/main/java/riot/
    jena/Experimental/riot-output/src/main/java/riot/other/
    jena/Experimental/riot-output/src/main/java/riot/other/GLib.java
    jena/Experimental/riot-output/src/main/java/riot/out/
    jena/Experimental/riot-output/src/main/java/riot/out/EscapeStr.java
      - copied, changed from r1435266, jena/Experimental/riot-output/src/main/java/out/EscapeStr.java
    jena/Experimental/riot-output/src/main/java/riot/out/NodeFmtLib.java
      - copied, changed from r1435266, jena/Experimental/riot-output/src/main/java/out/NodeFmtLib.java
    jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatter.java
      - copied, changed from r1435266, jena/Experimental/riot-output/src/main/java/out/NodeFormatter.java
    jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterBase.java
      - copied, changed from r1435266, jena/Experimental/riot-output/src/main/java/out/NodeFormatterBase.java
    jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterNT.java
      - copied, changed from r1435266, jena/Experimental/riot-output/src/main/java/out/NodeFormatterNT.java
    jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterTTL.java
      - copied, changed from r1435266, jena/Experimental/riot-output/src/main/java/out/NodeFormatterTTL.java
    jena/Experimental/riot-output/src/main/java/riot/out/OutputUtils.java
      - copied, changed from r1435266, jena/Experimental/riot-output/src/main/java/out/OutputUtils.java
    jena/Experimental/riot-output/src/main/java/riot/writer/
    jena/Experimental/riot-output/src/main/java/riot/writer/PROJECT_RiotWriter.java
    jena/Experimental/riot-output/src/main/java/riot/writer/TW2.java
    jena/Experimental/riot-output/src/main/java/riot/writer/TriGWriter.java
    jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriter2.java
    jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriterBlocks.java
    jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriterFlat.java
    jena/Experimental/riot-output/src/main/java/riot/writer/WriterConst.java
Removed:
    jena/Experimental/riot-output/src/main/java/dev/OutputMain.java
    jena/Experimental/riot-output/src/main/java/out/
Modified:
    jena/Experimental/riot-output/D.ttl
    jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java

Added: jena/Experimental/riot-output/D.trig
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/D.trig?rev=1435565&view=auto
==============================================================================
--- jena/Experimental/riot-output/D.trig (added)
+++ jena/Experimental/riot-output/D.trig Sat Jan 19 14:52:56 2013
@@ -0,0 +1,24 @@
+@prefix : <http://example/> .
+
+
+{ :s :p :o ;
+     :pppppp :o  ;
+     :pppppp :o  .
+  :s1 :qqq :o .
+}
+
+{
+  :longname1234567890 :p :o1 , :o2 .
+}
+
+
+:g1 { :s1 :p1 :o1 .} 
+:g1 { :s1 :p1 :o2 } 
+:g2 { :s2 :p2 :o2 ;
+          :p3 :o2  .
+	  :x :y 123 }
+{ :s :p :o . }
+
+@prefix ex: <http://example/> .
+
+{ ex:x ex:p ex:z }

Modified: jena/Experimental/riot-output/D.ttl
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/D.ttl?rev=1435565&r1=1435564&r2=1435565&view=diff
==============================================================================
--- jena/Experimental/riot-output/D.ttl (original)
+++ jena/Experimental/riot-output/D.ttl Sat Jan 19 14:52:56 2013
@@ -2,5 +2,7 @@
 @prefix rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
 @prefix rdfs:    <http://www.w3.org/2000/01/rdf-schema#> .
 
-:s :p :o .
+:s :pppp :o .
 :s :p (1 2) .
+:s :pppp :o .
+:s1 :pppp :o .

Copied: jena/Experimental/riot-output/src/main/java/dev/MainOutput.java (from r1435266, jena/Experimental/riot-output/src/main/java/dev/OutputMain.java)
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/dev/MainOutput.java?p2=jena/Experimental/riot-output/src/main/java/dev/MainOutput.java&p1=jena/Experimental/riot-output/src/main/java/dev/OutputMain.java&r1=1435266&r2=1435565&rev=1435565&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/dev/OutputMain.java (original)
+++ jena/Experimental/riot-output/src/main/java/dev/MainOutput.java Sat Jan 19 14:52:56 2013
@@ -22,7 +22,7 @@ package dev;
 import org.apache.jena.riot.RDFDataMgr ;
 import org.apache.jena.riot.system.StreamRDF ;
 
-public class OutputMain
+public class MainOutput
 {
     public static void main(String[] args)
     {

Added: jena/Experimental/riot-output/src/main/java/dev/MainWriter.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/dev/MainWriter.java?rev=1435565&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/dev/MainWriter.java (added)
+++ jena/Experimental/riot-output/src/main/java/dev/MainWriter.java Sat Jan 19 14:52:56 2013
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dev;
+
+import java.io.ByteArrayInputStream ;
+import java.io.ByteArrayOutputStream ;
+
+import org.apache.jena.atlas.lib.StrUtils ;
+import org.apache.jena.riot.RDFDataMgr ;
+import riot.writer.TriGWriter ;
+import riot.writer.TurtleWriter2 ;
+import riot.writer.TurtleWriterFlat ;
+
+import com.hp.hpl.jena.query.Dataset ;
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.rdf.model.ModelFactory ;
+
+public class MainWriter
+{
+    public static void main(String ...args)
+    {
+        writeTTL() ;
+        //writeTriG() ;
+    }
+    
+    public static void writeTriG()
+    {
+        Dataset ds = RDFDataMgr.loadDataset("W.trig") ;
+        TriGWriter.write(System.out, ds) ;
+    }
+    
+    public static void writeTTL()
+    {
+        Model m = RDFDataMgr.loadModel("W.ttl") ;
+        TurtleWriterFlat.write(System.out, m, m.getNsPrefixMap()) ;
+        System.out.println("----------------------------------") ;
+        
+        ByteArrayOutputStream out = new ByteArrayOutputStream() ;
+        TurtleWriter2.write(out, m) ;
+        ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()) ;
+        String s = StrUtils.fromUTF8bytes(out.toByteArray()) ;
+        Model m2 = ModelFactory.createDefaultModel() ;
+        m2.read(in, null, "TTL") ;
+        if ( ! m.isIsomorphicWith(m2) )
+            System.out.println("**** DIFFERENT") ;
+        
+        m.write(System.out, "TTL") ;
+    }
+
+    
+}
+

Modified: jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java?rev=1435565&r1=1435564&r2=1435565&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java (original)
+++ jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java Sat Jan 19 14:52:56 2013
@@ -26,21 +26,74 @@ import org.apache.jena.atlas.lib.Tuple ;
 import org.apache.jena.riot.out.NodeToLabel ;
 import org.apache.jena.riot.system.PrefixMap ;
 import org.apache.jena.riot.system.StreamRDF ;
-import out.NodeFormatterTTL ;
+import riot.out.NodeFormatterTTL ;
 
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.graph.Triple ;
 import com.hp.hpl.jena.sparql.core.Quad ;
 
+/** An output of triples / quads that is streaming.
+ *  It writes something that is easier to read than
+ *  N-triples, N-quads but it's not full pretty printing
+ *  which usually requires analysing the data before any output
+ *  hence is not streaming.   
+ *  
+ *  If fed only quads, the output is valid TriG. 
+ *  If fed only triples, the output is valid Turtle. 
+ */
+
 class PrintTurtleStreamRDF implements StreamRDF
 {
+    // TODO
+    // Min width for properties?
+    // better layering and state machine
+    
+    /*
+     * start graph
+     * finish graph
+     * data.
+     */
+    
+    // When false, gets 
+    // :g1 { ... }
+    // :g2 { ... }
+    private static final boolean NLAFTERGRAPH =  true ;
+    private static final int INDENT_MIN_S = 2 ;
+    private static final int INDENT_MAX_S = 8 ;
+    private static final int INDENT_G = 4 ;
+    
+    private boolean lastWasTripleData = false ;
+    private boolean lastWasQuadData = false ;
+    private boolean lastWasDirective = false ;
+
     private final PrefixMap pMap ;
     private final NodeFormatterTTL fmt ;
     private final IndentedWriter out ;
+
+    private Node lastSubject = null ;
+    private Node lastGraph = null ;     // null -> unset : Quad. 
     
-    private static final int INDENT_G = 2 ;
-    private static final int INDENT_S = 4 ;
+    // --- Indent management.
+    private int currentGraphIndent = 0;
+    private int currentSubjectIndent = 0 ;
+
+    private void setGraphIndent(int x)
+    {
+        if ( x < INDENT_G ) x = INDENT_G ;
+        currentGraphIndent = x ;
+    }
+
+    private void setSubjectIndent(int x)
+    {
+        if ( x < INDENT_MIN_S ) x = INDENT_MIN_S ;
+        if ( x > INDENT_MAX_S ) x = INDENT_MAX_S ;
+        currentSubjectIndent = x ;
+    }
     
+    private int graphIndent() { return currentGraphIndent ; }
+    private int subjectIndent() { return currentSubjectIndent ; }
+    // ----
+
     public PrintTurtleStreamRDF(OutputStream output)
     { 
         this.out = new IndentedWriter(output) ;
@@ -52,16 +105,11 @@ class PrintTurtleStreamRDF implements St
 
     @Override
     public void start()
-    {}
+    {
+        reset() ;
+    }
 
-    private boolean lastWasTripleData = false ;
-    private boolean lastWasQuadData = false ;
-    private boolean lastWasDirective = false ;
-    
-    private Node lastSubject = null ;
-    private Node lastGraph = null ;
-    
-    private void out(Node n)
+    private void outputNode(Node n)
     {
         fmt.format(out, n) ;
     }
@@ -73,6 +121,8 @@ class PrintTurtleStreamRDF implements St
         lastWasDirective = false ;
         lastSubject = null ;
         lastGraph = null ;
+        // Shouldn't be necessary - if it is some other code is not managing inc/dec indents.
+        //out.setAbsoluteIndent(0) ;
     }
     
     private void printPre()
@@ -85,38 +135,50 @@ class PrintTurtleStreamRDF implements St
         }
     }
     
+    private void DEBUG(String fmt, Object...args)
+    {
+        int loc = out.getCol() ;            // Absolute
+        int off = out.getAbsoluteIndent() ;
+        out.ensureStartOfLine();
+        out.setAbsoluteIndent(0) ;
+        out.println(String.format(fmt, args)) ;
+        out.setAbsoluteIndent(off) ;
+        out.ensureStartOfLine();
+        out.pad(loc, true) ;
+    }
+    
     private void print(Node g, Node s, Node p, Node o)
     {
         printPre() ;
+        endGraph(g) ;
 
-        // End of graph
-        if ( lastSubject != null && ! equal(lastGraph, g) )
-        {
-            //out.println() ;
-            out.print(" ") ;
-            out.decIndent(INDENT_G) ;
-            out.decIndent(INDENT_S) ;
-            out.println("}") ;
-            lastSubject = null ;
-            lastGraph = null ;
-            
-        }
         // Start graph
         if ( lastGraph == null )
         {
-            if ( lastSubject != null )
+            lastSubject = null ;
+            if ( g == Quad.defaultGraphNodeGenerated )
             {
-                out.decIndent(INDENT_S) ;
-                out.println(" .") ;
+                out.print("{ ") ;
+                //setGraphIndent(INDENT_G) ;
+                setGraphIndent(2) ;
+                // YUK!!!!
+                currentGraphIndent = 2 ;
+//                if ( NLAFTERGRAPH )
+//                    out.println();
             }
-            lastSubject = null ;
-            if ( g != null )
+            else
             {
-                fmt.format(out, g) ;
-                out.print(" ") ;
+                outputNode(g) ;
+                out.print(" { ") ;
+                if ( NLAFTERGRAPH )
+                {
+                    out.println() ;
+                    setGraphIndent(INDENT_G) ;
+                }
+                else
+                    setGraphIndent(out.getCol()) ;
             }
-            out.println("{") ;
-            out.incIndent(INDENT_G) ;
+            out.incIndent(graphIndent()) ;
         }
         print$(s,p,o) ;
         lastGraph = g ;
@@ -135,25 +197,32 @@ class PrintTurtleStreamRDF implements St
         if ( equal(lastSubject, s) ) 
         {
             out.println(" ;") ;
-            fmt.format(out, p) ;
+            //DEBUG("[pad=%d]", lastSubjectOffset);
+            out.pad(subjectIndent()) ;
+            out.flush();
+            outputNode(p) ;
             out.print(' ') ;
-            fmt.format(out, o) ;
+            outputNode(o) ;
         } else {
             // Change subject, same graph. 
             if ( lastSubject != null )
-            {
-                // DRY
-                out.print(" .") ;
-                out.decIndent(INDENT_S) ;
-                out.println() ;
-            }
+                endTriples() ;
             
-            fmt.format(out, s) ;
+            int x1 = out.getCol() ;
+            outputNode(s) ;
             out.print(' ') ;
-            fmt.format(out, p) ;
+            
+            out.flush();
+            
+            int x2 = out.getCol() ;
+            setSubjectIndent(out.getCurrentOffset()) ;
+            out.pad(subjectIndent()) ;
+            //DEBUG("[indent=%d  x1=%d  x2=%d  lastSubjectOffset=%d]", out.getAbsoluteIndent(), x1,x2,lastSubjectOffset);
+            
+            outputNode(p) ;
             out.print(' ') ;
-            fmt.format(out, o) ;
-            out.incIndent(INDENT_S) ;
+            outputNode(o) ;
+            //out.incIndent(INDENT_S) ;
 
         }
         lastSubject = s ;
@@ -175,6 +244,9 @@ class PrintTurtleStreamRDF implements St
         Node s = quad.getSubject() ;
         Node p = quad.getPredicate() ;
         Node o = quad.getObject() ;
+        if ( g == null )
+            // Don't have g as null for a triple.
+            g = Quad.defaultGraphNodeGenerated ;
         print(g, s, p, o) ;
     }
 
@@ -188,34 +260,42 @@ class PrintTurtleStreamRDF implements St
         
     }
 
-    private void endData()
+    private void endGraph(Node g)
     {
-        if ( lastWasTripleData )
-        {
-            out.println(" .") ;
-            out.decIndent(INDENT_S) ;
-        }
-        
-        if ( lastWasQuadData )
+        if ( lastGraph == null )
+            return ;
+            
+        // End of graph
+        if ( ! equal(lastGraph, g) )
         {
-            // DRY
             out.print(" ") ;
-            out.decIndent(INDENT_G) ;
-            out.decIndent(INDENT_S) ;
-            out.println("}") ;
+            out.println(" }") ;
+            out.println() ;
+            out.decIndent(graphIndent()) ;
+            lastSubject = null ;
+            lastGraph = null ;
         }
-        
+    }
+
+    private void endTriples()
+    {
+        out.println(" .") ;
+        lastSubject = null ;
+    }
+    
+    private void endData()
+    {
+        if ( lastWasQuadData )
+            endGraph(null) ;
+        if ( lastWasTripleData )
+            endTriples() ;
         reset() ;
     }
     
     @Override
     public void prefix(String prefix, String iri)
     {
-        boolean b = lastWasTripleData || lastWasQuadData ;
         endData() ;
-        if ( b ) 
-            out.println() ;
-        
         lastWasDirective = true ;
 
         out.print("@prefix ") ;

Added: jena/Experimental/riot-output/src/main/java/riot/other/GLib.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/other/GLib.java?rev=1435565&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/other/GLib.java (added)
+++ jena/Experimental/riot-output/src/main/java/riot/other/GLib.java Sat Jan 19 14:52:56 2013
@@ -0,0 +1,131 @@
+/**
+ * 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 riot.other;
+
+import java.util.Iterator ;
+
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.iterator.Transform ;
+
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+import com.hp.hpl.jena.util.iterator.ExtendedIterator ;
+
+/** A collection of Graph/Triple/Node related functions */
+public class GLib
+{
+    /** Convert null to Node.ANY */
+    public static Node nullAsAny(Node x) { return nullAsDft(x, Node.ANY) ; }
+    
+    /** Convert null to some default Node */
+    public static Node nullAsDft(Node x, Node dft) { return x==null ? dft : x ; }
+    
+    // DISTINCT means these are space using.
+    /** List the subjects in a graph (no duplicates) */
+    public static Iterator<Node> listSubjects(Graph graph)
+    {
+        ExtendedIterator<Triple> iter = graph.find(Node.ANY, Node.ANY, Node.ANY) ;
+        return Iter.iter(iter).map(projectTripeSubject).distinct() ;
+    }
+
+    /** List the predicates in a graph (no duplicates) */
+    public static Iterator<Node> listPredicates(Graph graph)
+    {
+        ExtendedIterator<Triple> iter = graph.find(Node.ANY, Node.ANY, Node.ANY) ;
+        return Iter.iter(iter).map(projectTripePredicate).distinct() ;
+    }
+    
+    /** List the objects in a graph (no duplicates) */
+    public static Iterator<Node> listObjects(Graph graph)
+    {
+        ExtendedIterator<Triple> iter = graph.find(Node.ANY, Node.ANY, Node.ANY) ;
+        return Iter.iter(iter).map(projectTripeObject).distinct() ;
+    }
+    
+    private static Transform<Quad, Triple> transformQuad2Triple = new Transform<Quad, Triple> () {
+        @Override
+        public Triple convert(Quad quad)    { return quad.asTriple() ; }
+    } ;
+
+    /** Project quads to triples */
+    public static Iter<Triple> quads2triples(Iterator<Quad> iter)
+    {
+        return Iter.iter(iter).map(transformQuad2Triple) ;
+    }
+
+    /** Project quad to graphname */
+    public static Iterator<Node> quad2graphName(Iterator<Quad> iter)
+    { return Iter.map(iter, projectQuadGraphName) ; }
+    
+    /** Project quad to graphname */
+    public static Iterator<Node> quad2subject(Iterator<Quad> iter)
+    { return Iter.map(iter, projectQuadSubject) ; }
+    
+    /** Project quad to predicate */
+    public static Iterator<Node> quad2predicate(Iterator<Quad> iter)
+    { return Iter.map(iter, projectQuadPredicate) ; }
+    
+    /** Project quad to object */
+    public static Iterator<Node> quad2object(Iterator<Quad> iter)
+    { return Iter.map(iter, projectQuadObject) ; }
+    
+    /** Project triple to subject */ 
+    public static Iterator<Node> triple2subject(Iterator<Triple> iter)
+    { return Iter.map(iter, projectTripeSubject) ; }
+    
+    /** Project triple to predicate */ 
+    public static Iterator<Node> triple2predicate(Iterator<Triple> iter)
+    { return Iter.map(iter, projectTripePredicate) ; }
+    
+    /** Project triple to object */ 
+    public static Iterator<Node> triple2object(Iterator<Triple> iter)
+    { return Iter.map(iter, projectTripeObject) ; }
+
+    /** Transform quad to graphname */
+    public static Transform<Quad, Node> projectQuadGraphName = new Transform<Quad, Node>() {
+        @Override  public Node convert(Quad quad) { return quad.getGraph() ; }
+    } ;
+    /** Transform quad to subject */
+    public static Transform<Quad, Node> projectQuadSubject = new Transform<Quad, Node>() {
+        @Override  public Node convert(Quad quad) { return quad.getSubject() ; }
+    } ;
+    /** Transform quad to predicate */
+    public static Transform<Quad, Node> projectQuadPredicate = new Transform<Quad, Node>() {
+        @Override public Node convert(Quad quad) { return quad.getPredicate() ; }
+    } ;
+    /** Transform quad to object */
+    public static Transform<Quad, Node> projectQuadObject = new Transform<Quad, Node>() {
+        @Override public Node convert(Quad quad) { return quad.getObject() ; }
+    } ;
+    /** Transform triple to subject */ 
+    public static Transform<Triple, Node> projectTripeSubject   = new Transform<Triple, Node>() {
+        @Override public Node convert(Triple triple) { return triple.getSubject() ; }
+    } ;
+    /** Transform triple to predicate */ 
+    public static Transform<Triple, Node> projectTripePredicate = new Transform<Triple, Node>() {
+        @Override public Node convert(Triple triple) { return triple.getPredicate() ; }
+    } ;
+    /** Transform triple to object */ 
+    public static Transform<Triple, Node> projectTripeObject    = new Transform<Triple, Node>() {
+        @Override public Node convert(Triple triple) { return triple.getObject() ; }
+    } ;
+}
+

Copied: jena/Experimental/riot-output/src/main/java/riot/out/EscapeStr.java (from r1435266, jena/Experimental/riot-output/src/main/java/out/EscapeStr.java)
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/out/EscapeStr.java?p2=jena/Experimental/riot-output/src/main/java/riot/out/EscapeStr.java&p1=jena/Experimental/riot-output/src/main/java/out/EscapeStr.java&r1=1435266&r2=1435565&rev=1435565&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/out/EscapeStr.java (original)
+++ jena/Experimental/riot-output/src/main/java/riot/out/EscapeStr.java Sat Jan 19 14:52:56 2013
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-package out;
+package riot.out;
 
 import org.apache.jena.atlas.io.IndentedLineBuffer ;
 import org.apache.jena.atlas.io.IndentedWriter ;

Copied: jena/Experimental/riot-output/src/main/java/riot/out/NodeFmtLib.java (from r1435266, jena/Experimental/riot-output/src/main/java/out/NodeFmtLib.java)
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/out/NodeFmtLib.java?p2=jena/Experimental/riot-output/src/main/java/riot/out/NodeFmtLib.java&p1=jena/Experimental/riot-output/src/main/java/out/NodeFmtLib.java&r1=1435266&r2=1435565&rev=1435565&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/out/NodeFmtLib.java (original)
+++ jena/Experimental/riot-output/src/main/java/riot/out/NodeFmtLib.java Sat Jan 19 14:52:56 2013
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-package out;
+package riot.out;
 
 import java.net.MalformedURLException ;
 import java.util.Map ;

Copied: jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatter.java (from r1435266, jena/Experimental/riot-output/src/main/java/out/NodeFormatter.java)
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatter.java?p2=jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatter.java&p1=jena/Experimental/riot-output/src/main/java/out/NodeFormatter.java&r1=1435266&r2=1435565&rev=1435565&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/out/NodeFormatter.java (original)
+++ jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatter.java Sat Jan 19 14:52:56 2013
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-package out;
+package riot.out;
 
 
 import org.apache.jena.atlas.io.IndentedWriter ;

Copied: jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterBase.java (from r1435266, jena/Experimental/riot-output/src/main/java/out/NodeFormatterBase.java)
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterBase.java?p2=jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterBase.java&p1=jena/Experimental/riot-output/src/main/java/out/NodeFormatterBase.java&r1=1435266&r2=1435565&rev=1435565&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/out/NodeFormatterBase.java (original)
+++ jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterBase.java Sat Jan 19 14:52:56 2013
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-package out;
+package riot.out;
 
 import org.apache.jena.atlas.io.IndentedWriter ;
 

Copied: jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterNT.java (from r1435266, jena/Experimental/riot-output/src/main/java/out/NodeFormatterNT.java)
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterNT.java?p2=jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterNT.java&p1=jena/Experimental/riot-output/src/main/java/out/NodeFormatterNT.java&r1=1435266&r2=1435565&rev=1435565&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/out/NodeFormatterNT.java (original)
+++ jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterNT.java Sat Jan 19 14:52:56 2013
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-package out;
+package riot.out;
 
 
 import org.apache.jena.atlas.io.IndentedWriter ;

Copied: jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterTTL.java (from r1435266, jena/Experimental/riot-output/src/main/java/out/NodeFormatterTTL.java)
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterTTL.java?p2=jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterTTL.java&p1=jena/Experimental/riot-output/src/main/java/out/NodeFormatterTTL.java&r1=1435266&r2=1435565&rev=1435565&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/out/NodeFormatterTTL.java (original)
+++ jena/Experimental/riot-output/src/main/java/riot/out/NodeFormatterTTL.java Sat Jan 19 14:52:56 2013
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-package out;
+package riot.out;
 
 import java.net.MalformedURLException ;
 

Copied: jena/Experimental/riot-output/src/main/java/riot/out/OutputUtils.java (from r1435266, jena/Experimental/riot-output/src/main/java/out/OutputUtils.java)
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/out/OutputUtils.java?p2=jena/Experimental/riot-output/src/main/java/riot/out/OutputUtils.java&p1=jena/Experimental/riot-output/src/main/java/out/OutputUtils.java&r1=1435266&r2=1435565&rev=1435565&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/out/OutputUtils.java (original)
+++ jena/Experimental/riot-output/src/main/java/riot/out/OutputUtils.java Sat Jan 19 14:52:56 2013
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-package out;
+package riot.out;
 
 import java.io.IOException ;
 import java.io.Writer ;

Added: jena/Experimental/riot-output/src/main/java/riot/writer/PROJECT_RiotWriter.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/writer/PROJECT_RiotWriter.java?rev=1435565&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/writer/PROJECT_RiotWriter.java (added)
+++ jena/Experimental/riot-output/src/main/java/riot/writer/PROJECT_RiotWriter.java Sat Jan 19 14:52:56 2013
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package riot.writer;
+
+public class PROJECT_RiotWriter
+{
+    // Turtle writers:
+    // Pretty
+    // Blocks - same subject blocks, no object nesting, no lists.
+    // flat - ntriples+prefixes+numbers 
+    
+    
+    // TODO
+    // Turtle:
+    // Order subjects to write
+    //   ==> scan by subject, not triples
+
+    // Single pass analysis
+    
+    // Lists
+    //   Do before embeddable objects because list take precedence.
+    
+    // PredicateObjectLists
+    //   type to front.
+    // Property order is:
+    // 1 - rdf:type (as "a")
+    // 2 - other rdf: rdfs: namespace items (sorted)
+    // 3 - all other properties, sorted by URI (not qname)  
+    //     same properties together - with and without object lists
+    
+    // TriG:
+    // Turtle plus
+}
+

Added: jena/Experimental/riot-output/src/main/java/riot/writer/TW2.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/writer/TW2.java?rev=1435565&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/writer/TW2.java (added)
+++ jena/Experimental/riot-output/src/main/java/riot/writer/TW2.java Sat Jan 19 14:52:56 2013
@@ -0,0 +1,194 @@
+/**
+ * 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 riot.writer;
+
+import static riot.writer.WriterConst.PREFIX_IRI ;
+
+import java.util.* ;
+import java.util.Map.Entry ;
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+import org.apache.jena.atlas.lib.Pair ;
+
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.sparql.util.FmtUtils ;
+import com.hp.hpl.jena.util.iterator.ExtendedIterator ;
+import com.hp.hpl.jena.vocabulary.RDF ;
+
+/** Support code for the RIOT TurtleWriter */ 
+public class TW2
+{
+    static void writePrefixes(IndentedWriter out, Map<String, String> prefixMap)
+    {
+        if ( ! prefixMap.isEmpty() )
+        {
+            // prepare?
+            for ( Map.Entry <String, String> e : prefixMap.entrySet() )
+            {
+                TW2.print(out, "@prefix ") ;
+                TW2.print(out, e.getKey()) ;
+                TW2.print(out, ": ") ;
+                TW2.pad(out, PREFIX_IRI) ;
+                TW2.print(out, "<") ;
+                TW2.print(out, e.getValue()) ;   // Check?
+                TW2.print(out, ">") ;
+                TW2.print(out, " .") ;
+                out.println() ;
+            }
+        }
+    }
+
+    // Single, multi-function, pass over the graph 
+    // It alread scans all objects.
+
+    /** Find all well-formed lists */  
+    static Set<Triple> findLists(Graph graph)
+    {
+        
+        Set<Triple> listTriples = new HashSet<Triple>() ;
+        // Find the tail triple. 
+        ExtendedIterator<Triple> tails = graph.find(Node.ANY, RDF.Nodes.rest, RDF.Nodes.nil) ;
+        for ( ; tails.hasNext() ; )
+        {
+            Triple t = tails.next() ;
+            // Well formed?
+            // has exactly one rdf:first and one rdf:rest and nothing else.
+            
+            Node x = t.getSubject() ;
+            // ...
+        }
+        tails.close();
+        
+        return null ;
+    }
+
+    
+    static final boolean recordObjectMisses = true ; 
+    
+    /** Find all embeddable objects */  
+    @SuppressWarnings("null")
+    static Pair<Set<Node>, Set<Triple>> findOneConnectedBNodeObjects(Graph graph)
+    {
+        ExtendedIterator<Triple> iter = graph.find(Node.ANY, Node.ANY, Node.ANY) ;
+
+        Set<Node> bNodesObj1 = new HashSet<Node>()  ;        // The subject of exactly one triple.
+        Set<Triple> triplesObj1 = new HashSet<Triple>()  ;   // The triples of such a thing. 
+        
+        Set<Node> rejects = recordObjectMisses ? new HashSet<Node>() : null ;      // Nodes known not to meet the requirement.
+        
+        for ( ; iter.hasNext() ; )
+        {
+            Triple t = iter.next() ;
+            Node obj = t.getObject() ;
+            if ( ! obj.isBlank() )
+                continue ;
+            if ( rejects != null && rejects.contains(obj) )
+                continue ;
+            // No point checking bNodesObj1.
+            Node n = connectedOnce(graph, obj) ;
+            if ( n != null )
+            {
+                bNodesObj1.add(n) ;
+                // find triples to skip.
+                accTriplesOfSubject(triplesObj1, graph, obj) ;
+            }
+        }
+        iter.close() ;
+        return Pair.create(bNodesObj1, triplesObj1) ;
+    }
+
+    static Node connectedOnce(Graph graph, Node obj)
+    {
+        ExtendedIterator<Triple> iter = graph.find(Node.ANY, Node.ANY, obj) ;
+        int count = 0 ;
+        try {
+            if ( ! iter.hasNext() ) return null ;
+            iter.next() ;
+            if ( ! iter.hasNext() ) return obj ;
+            return null ;
+        } finally { iter.close() ; }
+    }
+    
+    static Collection<Triple> triplesOfSubject(Graph graph, Node subj)
+    {
+        Collection<Triple> x = new HashSet<Triple>() ;
+        accTriplesOfSubject(x, graph, subj) ;
+        return x ;
+    }
+
+    static void accTriplesOfSubject(Collection<Triple> acc, Graph graph, Node subj)
+    {
+        ExtendedIterator<Triple> iter = graph.find(subj, Node.ANY, Node.ANY) ;
+        for ( ; iter.hasNext() ; )
+            acc.add(iter.next()) ;
+        iter.close() ;
+    }
+
+    static void writeNode(IndentedWriter out, Node node, Map<String, String> prefixMap)
+    {
+        // See RIOT NodeFormatter
+        if ( node.isURI() )
+        {
+            String iri = node.getURI() ;
+            // Crude.
+            String x = abbreviate(iri, prefixMap) ;
+            if ( x != null )
+            {
+                print(out, x) ;
+                return ;
+            }
+        }
+        print(out, FmtUtils.stringForNode(node)) ;
+    }
+
+    /** Abbreviate an IRI or return null */
+    private static String abbreviate(String uriStr, Map<String, String> prefixMap)
+    {
+        for ( Entry<String, String> e : prefixMap.entrySet())
+        {
+            String prefix = e.getValue().toString() ;
+            
+            if ( uriStr.startsWith(prefix) )
+            {
+                String ln = uriStr.substring(prefix.length()) ;
+                if ( strSafeFor(ln, '/') && strSafeFor(ln, '#') && strSafeFor(ln, ':') )
+                    return e.getKey()+":"+ln ;
+            }
+        }
+        return null ;
+    }
+
+    static boolean strSafeFor(String str, char ch) { return str.indexOf(ch) == -1 ; }
+
+    private static void flush(IndentedWriter out) { out.flush() ; }
+
+    static void print(IndentedWriter out, String string)
+    {
+        out.print(string) ;
+        flush(out) ;
+    }
+
+    static void pad(IndentedWriter out, int col)
+    {
+        out.pad(col, true) ;
+    }
+}
+

Added: jena/Experimental/riot-output/src/main/java/riot/writer/TriGWriter.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/writer/TriGWriter.java?rev=1435565&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/writer/TriGWriter.java (added)
+++ jena/Experimental/riot-output/src/main/java/riot/writer/TriGWriter.java Sat Jan 19 14:52:56 2013
@@ -0,0 +1,74 @@
+/**
+ * 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 riot.writer;
+
+import java.io.OutputStream ;
+import java.util.Iterator ;
+import java.util.Map ;
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.query.Dataset ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+
+public class TriGWriter
+{
+    public static final int GRAPH_INDENT = 4 ;
+    
+    public static void write(OutputStream out, Dataset dataset)
+    {
+        write(out, dataset.asDatasetGraph(), dataset.getDefaultModel().getNsPrefixMap()) ;
+    }
+    
+    public static void write(OutputStream out, DatasetGraph dsg,  Map<String, String> prefixMap)
+    {
+        IndentedWriter iOut = new IndentedWriter(out, false) ;
+        Iterator<Node> graphNames = dsg.listGraphNodes() ;
+        
+        writeGraph(iOut, null, dsg.getDefaultGraph(),  prefixMap) ;
+        
+        for ( ; graphNames.hasNext() ; )
+        {
+            iOut.println() ;
+            Node gn = graphNames.next() ;
+            writeGraph(iOut, gn, dsg.getGraph(gn),  prefixMap) ;
+        }
+        iOut.flush() ;
+    }
+    
+    private static void writeGraph(IndentedWriter out, Node name, Graph graph,  Map<String, String> prefixMap)
+    {
+        if ( name != null )
+        {
+            TW2.writeNode(out, name, prefixMap) ;
+            out.print("  ") ;
+        }
+        out.println("{") ;
+        out.incIndent(GRAPH_INDENT) ;
+        TurtleWriterBlocks.write(out, graph, prefixMap) ;
+        
+        out.decIndent(GRAPH_INDENT) ;
+        out.ensureStartOfLine() ;
+        out.println("}") ;
+    }
+
+}
+

Added: jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriter2.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriter2.java?rev=1435565&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriter2.java (added)
+++ jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriter2.java Sat Jan 19 14:52:56 2013
@@ -0,0 +1,235 @@
+/**
+ * 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 riot.writer;
+
+import static riot.writer.WriterConst.* ;
+
+import java.io.OutputStream ;
+import java.util.* ;
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+import org.apache.jena.atlas.lib.Pair ;
+import riot.other.GLib ;
+
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.rdf.model.Model ;
+
+public class TurtleWriter2
+{
+
+    // Prepare prefixes.
+    // Need fast String=>prefix.
+    
+    public static void write(OutputStream out, Model model)
+    {
+        write(out, model.getGraph(), model.getNsPrefixMap()) ;
+    }
+    
+    public static void write(OutputStream out, Graph graph,  Map<String, String> prefixMap)
+    {
+        IndentedWriter iOut = new IndentedWriter(out, false) ;
+        write(iOut, graph, prefixMap) ;
+    }
+
+    // Call from TriG as well.
+    static void write(IndentedWriter out, Graph graph, Map<String, String> prefixMap)
+    {
+        write$(out, graph, prefixMap) ;
+        out.flush() ;
+    }
+    
+    // Call from TriG as well.
+    static void write$(IndentedWriter out, Graph graph, Map<String, String> prefixMap)
+    {
+        // Configuration.
+        Pair<Set<Node>, Set<Triple>> p = TW2.findOneConnectedBNodeObjects(graph) ;
+        Set<Node> bNodesObj1 = p.getLeft() ;
+        Set<Triple> triplesObj1 = p.getRight() ;
+        
+        // Lists
+        
+        
+        // Prefixes
+        TW2.writePrefixes(out, prefixMap) ;
+        if ( ! prefixMap.isEmpty() )
+            out.println();
+
+        // Or - listSubjects and sort.
+        Iterator<Node> subjects = GLib.listSubjects(graph) ;
+        writeBySubject(out, graph, subjects, bNodesObj1, triplesObj1, new HashSet<Object>(), prefixMap) ;
+    }
+    
+    static void writeBySubject(IndentedWriter out, Graph graph, 
+                               Iterator<Node> subjects, 
+                               Collection<Node> nestedObjects, Collection<Triple> skip, 
+                               Collection<Object> lists, 
+                               Map<String, String> prefixMap)
+    {
+        for ( ; subjects.hasNext() ; )
+        {
+            Node subj = subjects.next() ;
+            if ( nestedObjects.contains(subj) )
+                continue ;
+            
+            Collection<Triple> cluster = TW2.triplesOfSubject(graph, subj) ;
+            writeCluster(out, graph, subj, cluster, nestedObjects, prefixMap) ;
+        }
+    }
+    
+    
+    // Common subject
+    // Used by the blocks writer as well.
+    static void writeCluster(IndentedWriter out, Graph graph, Node subject, Collection<Triple> cluster, 
+                                     Collection<Node> nestedObjects, Map<String, String> prefixMap)
+    {
+        //int OFFSET = out.getIndent() ;
+        
+        if ( cluster.isEmpty() ) return ;
+        TW2.writeNode(out, subject, prefixMap) ;
+        
+        if ( out.getCol() > LONG_SUBJECT )
+            println(out) ;
+        else
+            gap(out) ;
+        out.incIndent(INDENT_PREDICATE) ;
+        out.pad() ;
+        writePredicateObjectList(out, graph, cluster, nestedObjects, prefixMap) ;
+        out.decIndent(INDENT_PREDICATE) ;
+        TW2.print(out, " .") ;  // Not perfect
+        println(out) ; 
+        println(out) ;
+    }
+    
+    // need to skip the triples nested.
+    
+    private static void writePredicateObjectList(IndentedWriter out, Graph graph, Collection<Triple> cluster, 
+                                                 Collection<Node> nestedObjects, Map<String, String> prefixMap)
+    {
+        boolean first = true ;
+        // Calc columns
+        
+        // Sort triples.
+        //  rdf:type
+        //  other rdf and rdfs
+        //  properties together
+        //  object lists?
+        // Find the colject pad column.
+        
+        
+        for ( Triple triple : cluster )
+        {
+            if ( first )
+                first = false ;
+            else
+            {
+                TW2.print(out, " ;") ;
+                println(out) ;
+            }
+            
+            // Write predicate.
+            int colPredicateStart = out.getCol() ;
+            
+            if ( ! prefixMap.containsValue(rdfNS) &&
+                triple.getPredicate().getURI().equals(iriType) )
+                // I prefer rdf:type when available.
+                TW2.print(out, "a") ;
+            else
+                TW2.writeNode(out, triple.getPredicate(), prefixMap) ;
+            int colPredicateFinish = out.getCol() ;
+            int wPredicate = (colPredicateFinish-colPredicateStart) ;
+            
+            // Needs to be relative?
+            if ( wPredicate > LONG_PREDICATE )
+                out.println() ;
+            else
+                gap(out) ;
+            
+            // Secondary one should be less
+            out.incIndent(INDENT_OBJECT) ;
+            out.pad() ;
+            Node obj = triple.getObject() ;
+            if ( nestedObjects.contains(obj) )
+                nestedObject(out, graph, obj, nestedObjects, prefixMap) ;
+            else
+                TW2.writeNode(out, triple.getObject(), prefixMap) ;
+            out.decIndent(INDENT_OBJECT) ;
+        }
+    }
+    
+    private static void nestedObject(IndentedWriter out, Graph graph, Node obj,
+                                     Collection<Node> nestedObjects, Map<String, String> prefixMap)
+    {
+        Collection<Triple> x = TW2.triplesOfSubject(graph, obj) ;
+        
+        if ( x.isEmpty() )
+        {
+            TW2.print(out, "[] ") ;
+            return ;
+        }
+
+        if ( x.size() == 1 )
+        {
+            TW2.print(out, "[ ") ;
+            // Includes nested object in triple.
+            writePredicateObjectList(out, graph, x, nestedObjects, prefixMap) ;
+            TW2.print(out, " ]") ;
+            return ;
+        }
+
+        // Two or more.
+        int here = out.getCol() ; // before "["
+        TW2.print(out, "[") ;
+        int i1 = out.getAbsoluteIndent() ;
+        out.setAbsoluteIndent(here) ;
+        // Inline: println(out) ;
+        out.incIndent(2) ;
+        writePredicateObjectList(out, graph, x, nestedObjects, prefixMap) ;
+        out.decIndent(2) ;
+        if ( true )
+        {
+            println(out) ; // Newline for "]"
+            TW2.print(out, "]") ;
+        }
+        else
+        {   // Compact
+            TW2.print(out, " ]") ;
+        }
+        out.setAbsoluteIndent(i1) ;
+    }
+    
+     
+    
+    // flush aggressively (debugging)
+    
+    private static void gap(IndentedWriter out)
+    {
+        out.print(' ', MIN_GAP) ;
+    }
+    
+    private static void println(IndentedWriter out)
+    {
+        out.println() ;
+        out.flush() ;
+    }
+
+    
+}
+

Added: jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriterBlocks.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriterBlocks.java?rev=1435565&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriterBlocks.java (added)
+++ jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriterBlocks.java Sat Jan 19 14:52:56 2013
@@ -0,0 +1,103 @@
+/**
+ * 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 riot.writer;
+
+import java.io.OutputStream ;
+import java.util.* ;
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+import org.apache.jena.atlas.iterator.PeekIterator ;
+
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.util.iterator.ExtendedIterator ;
+
+public class TurtleWriterBlocks
+{
+    public static void write(OutputStream out, Model model)
+    {
+        write(out, model.getGraph(), model.getNsPrefixMap()) ;
+    }
+    
+    public static void write(OutputStream out, Graph graph,  Map<String, String> prefixMap)
+    {
+        IndentedWriter iOut = new IndentedWriter(out, false) ;
+        write(iOut, graph, prefixMap) ;
+    }
+    
+    static void write(IndentedWriter out, Graph graph, Map<String, String> prefixMap)
+    {
+        // Lists
+        TW2.writePrefixes(out, prefixMap) ;
+        if ( ! prefixMap.isEmpty() )
+            out.println();
+        writeTriples(out, graph, graph.find(Node.ANY, Node.ANY, Node.ANY), prefixMap) ;
+    }
+    
+    
+    // Top level writer.
+    // Write blocks of same-subject triples, skipping anything we are going to process specially inline.
+    // If the collections are empty, this is about as good as streaming writing gets for Turtle.
+    
+    // Change this to be a pure streaming, nested writer.
+    static void writeTriples(IndentedWriter out, Graph graph, 
+                             ExtendedIterator<Triple> triples, 
+                             Map<String, String> prefixMap) 
+    {
+        Collection<Node> nestedObjects = Collections.emptyList() ; 
+        Collection<Triple> skip = Collections.emptyList() ;
+        Collection<Object> lists = Collections.emptyList() ;
+            
+        PeekIterator<Triple> stream = PeekIterator.create(triples) ;
+        List<Triple> cluster = new ArrayList<Triple>() ;
+        Node subject = null ;
+        for ( ; ; )
+        {
+            cluster.clear() ;
+            for ( ; stream.hasNext() ; )
+            {
+                Triple t = stream.peek() ;
+                if ( skip != null && skip.contains(t) )
+                {
+                    stream.next() ;
+                    continue ;
+                }
+                
+                if ( subject == null )
+                    subject = t.getSubject() ;
+                else if ( ! subject.equals(t.getSubject()) )
+                    break ;
+                cluster.add(t) ;
+                stream.next() ;
+            }
+            if ( subject != null )
+            {
+                TurtleWriter2.writeCluster(out, graph, subject, cluster, nestedObjects, prefixMap) ;
+                subject = null ;
+            }
+            else 
+                break ;
+        }
+        triples.close() ;
+    }
+    
+}
+

Added: jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriterFlat.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriterFlat.java?rev=1435565&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriterFlat.java (added)
+++ jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriterFlat.java Sat Jan 19 14:52:56 2013
@@ -0,0 +1,80 @@
+/**
+ * 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 riot.writer;
+
+import java.io.OutputStream ;
+import java.util.Iterator ;
+import java.util.Map ;
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.rdf.model.Model ;
+
+/** Write Turtle as one line of prefixed names */   
+public class TurtleWriterFlat
+{
+    static public final int colWidth = 8 ; 
+    static public final int predCol = 8 ;
+    static public final int objCol = 8+predCol ;
+    
+    public static void write(OutputStream out, Model model, Map<String, String> prefixes)
+    {
+        IndentedWriter iOut = new IndentedWriter(out) ;
+        write(iOut, model.getGraph(), prefixes) ;
+    }
+    
+    public static void write(IndentedWriter out, Model model, Map<String, String> prefixes)
+    {
+        write(out, model.getGraph(), prefixes) ;
+    }
+    
+    public static void write(IndentedWriter out, Graph graph, Map<String, String> prefixes) 
+    {
+        TW2.writePrefixes(out, prefixes) ;
+        if ( ! prefixes.isEmpty() )
+            out.println();
+        
+        Iterator<Triple> iter = graph.find(Node.ANY, Node.ANY, Node.ANY) ;
+        
+        for ( ; iter.hasNext() ; )
+        {
+            Triple triple = iter.next() ;
+            
+            Node s = triple.getSubject() ;
+            TW2.writeNode(out, s, prefixes) ;
+            
+            Node p = triple.getPredicate() ;
+            //out.pad(predCol-1) ;
+            out.print(" ") ;
+            TW2.writeNode(out, p, prefixes) ;
+            
+            Node o = triple.getObject() ;
+            //out.pad(objCol-1) ;
+            out.print(" ") ;
+            TW2.writeNode(out, o, prefixes) ;
+
+            out.println(" .") ; 
+        }
+        
+        out.flush() ;
+    }
+}

Added: jena/Experimental/riot-output/src/main/java/riot/writer/WriterConst.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/writer/WriterConst.java?rev=1435565&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/writer/WriterConst.java (added)
+++ jena/Experimental/riot-output/src/main/java/riot/writer/WriterConst.java Sat Jan 19 14:52:56 2013
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package riot.writer;
+
+import com.hp.hpl.jena.vocabulary.RDF ;
+
+public class WriterConst
+{
+    public static final int LONG_SUBJECT = 20 ;
+    public static final int LONG_PREDICATE = 30 ;
+    public static final int PREFIX_IRI = 15;
+    
+    // Column widths.
+    public static int COLW_SUBJECT = 6 ;
+    public static int COLW_PREDICATE = 8 ;
+    
+    // Column for start of predicate  
+    public static final int INDENT_PREDICATE = 8 ;
+    
+    // Column for start of object  
+    // Usually this is exceeded and predicate, objects are print with min gap. 
+    public static final int INDENT_OBJECT = 8 ;
+    
+    public static final String iriType = RDF.type.getURI() ;
+    
+    public static final int MIN_GAP = 2 ;
+    
+    public static final String rdfNS = RDF.getURI() ;
+
+}
+