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/21 22:02:31 UTC

svn commit: r1436616 - in /jena/Experimental/riot-output: ./ src/main/java/dev/ src/main/java/riot/writer/ testing/ testing/RIOT/ testing/RIOT/Writer/

Author: andy
Date: Mon Jan 21 21:02:31 2013
New Revision: 1436616

URL: http://svn.apache.org/viewvc?rev=1436616&view=rev
Log:
New Turtle writers: Pretty, streaming, blocks, flat.
Early cut at tests using round tripping of writer and parser.

Added:
    jena/Experimental/riot-output/src/main/java/dev/PROJECT_RiotWriter.java
      - copied, changed from r1435565, jena/Experimental/riot-output/src/main/java/riot/writer/PROJECT_RiotWriter.java
    jena/Experimental/riot-output/src/main/java/dev/PrintStreamRDF.java
      - copied, changed from r1435565, jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java
    jena/Experimental/riot-output/src/main/java/riot/writer/TestRIOTWriter.java
    jena/Experimental/riot-output/src/main/java/riot/writer/WriterContext.java
    jena/Experimental/riot-output/testing/
    jena/Experimental/riot-output/testing/RIOT/
    jena/Experimental/riot-output/testing/RIOT/Writer/
    jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-00.ttl
    jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-01.ttl
    jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-02.ttl
    jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-03.ttl
    jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-04.ttl
    jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-05.ttl
    jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-06.ttl
    jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-07.ttl
    jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-08.ttl
    jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-09.ttl
    jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-10.ttl
Removed:
    jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java
    jena/Experimental/riot-output/src/main/java/riot/writer/PROJECT_RiotWriter.java
Modified:
    jena/Experimental/riot-output/W.ttl
    jena/Experimental/riot-output/src/main/java/dev/MainOutput.java
    jena/Experimental/riot-output/src/main/java/dev/MainWriter.java
    jena/Experimental/riot-output/src/main/java/riot/writer/TW2.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/WriterConst.java

Modified: jena/Experimental/riot-output/W.ttl
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/W.ttl?rev=1436616&r1=1436615&r2=1436616&view=diff
==============================================================================
--- jena/Experimental/riot-output/W.ttl (original)
+++ jena/Experimental/riot-output/W.ttl Mon Jan 21 21:02:31 2013
@@ -2,19 +2,11 @@
 @prefix ns: <http://example/ns#> .
 @prefix rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
 
-:s ns:p1 <http://other/planet> .
-:s ns:p2 123 .
-:s ns:p3 [] .
-:s a :T .
+@prefix :     <http://example/> .
+@prefix ns:   <http://example/ns#> .
+@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
 
-:s ns:p4 "a","b" .
+# bad list
+:x :p3 _:bad .
 
-:z :p1 _:a .
-:z :p2 _:a .
-
-:a :q1 (1 2 3) .
-:a :q2 () .
-
-<http://example2/LONGSUBJECT_URI> :p "foo" .
-:s1 <http://example2/LONGPREDICATE_URI>  "foo" .
-:s1 <http://example2/VERYVERY_VERY_VERY_LONGPREDICATE_URI>  "foo" .
\ No newline at end of file
+_:bad rdf:rest (1 2 3) .

Modified: jena/Experimental/riot-output/src/main/java/dev/MainOutput.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/dev/MainOutput.java?rev=1436616&r1=1436615&r2=1436616&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/dev/MainOutput.java (original)
+++ jena/Experimental/riot-output/src/main/java/dev/MainOutput.java Mon Jan 21 21:02:31 2013
@@ -26,10 +26,10 @@ public class MainOutput
 {
     public static void main(String[] args)
     {
-        StreamRDF dst = new PrintTurtleStreamRDF(System.out);
+        StreamRDF dst = new PrintStreamRDF(System.out);
         RDFDataMgr.parse(dst, "D.ttl") ;
         System.out.println("--------") ;
-        dst = new PrintTurtleStreamRDF(System.out);
+        dst = new PrintStreamRDF(System.out);
         RDFDataMgr.parse(dst, "D.trig") ;
         
         System.out.println("DONE") ;

Modified: 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=1436616&r1=1436615&r2=1436616&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/dev/MainWriter.java (original)
+++ jena/Experimental/riot-output/src/main/java/dev/MainWriter.java Mon Jan 21 21:02:31 2013
@@ -20,16 +20,28 @@ package dev;
 
 import java.io.ByteArrayInputStream ;
 import java.io.ByteArrayOutputStream ;
+import java.util.Iterator ;
+import java.util.Map.Entry ;
 
 import org.apache.jena.atlas.lib.StrUtils ;
+import org.apache.jena.iri.IRI ;
 import org.apache.jena.riot.RDFDataMgr ;
+import org.apache.jena.riot.system.PrefixMap ;
+import org.apache.jena.riot.system.StreamRDF ;
 import riot.writer.TriGWriter ;
 import riot.writer.TurtleWriter2 ;
+import riot.writer.TurtleWriterBlocks ;
 import riot.writer.TurtleWriterFlat ;
 
+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.query.Dataset ;
 import com.hp.hpl.jena.rdf.model.Model ;
 import com.hp.hpl.jena.rdf.model.ModelFactory ;
+import com.hp.hpl.jena.shared.PrefixMapping ;
+import com.hp.hpl.jena.sparql.core.DatasetGraph ;
+import com.hp.hpl.jena.sparql.core.Quad ;
 
 public class MainWriter
 {
@@ -47,22 +59,100 @@ public class MainWriter
     
     public static void writeTTL()
     {
-        Model m = RDFDataMgr.loadModel("W.ttl") ;
-        TurtleWriterFlat.write(System.out, m, m.getNsPrefixMap()) ;
-        System.out.println("----------------------------------") ;
+        String fn = "W.ttl" ;
         
+        Model m = RDFDataMgr.loadModel(fn) ;
+        
+        if ( false )
+        {
+            System.out.println("# Write new (flat)") ;
+            TurtleWriterFlat.write(System.out, m, m.getNsPrefixMap()) ;
+            System.out.println("----------------------------------") ;
+        }
+        if ( true )
+        {
+            System.out.println("# Write new (Pretty)") ;
+            TurtleWriter2.write(System.out, m) ;
+            System.out.println("----------------------------------") ;
+        }
+        if ( false )
+        {
+            System.out.println("# Write new (blocks)") ;
+            TurtleWriterBlocks.write(System.out, m) ;
+            System.out.println("----------------------------------") ;
+        }
+        if ( false )
+        {
+            System.out.println("# Write stream") ;
+            StreamRDF dest = new PrintStreamRDF(System.out) ;
+            toStream(m.getGraph(), dest) ;
+            System.out.println("----------------------------------") ;
+        }
+        if ( false )
+        {
+            System.out.println("# Write old") ;
+            m.write(System.out, "TTL") ;
+            System.out.println("----------------------------------") ;
+        }
+
+        // check.
         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") ;
+            System.out.println("---------------") ;
+            m.write(System.out, "N-TRIPLES") ;
+            System.out.println("---------------") ;
+            m2.write(System.out, "N-TRIPLES") ;
+            System.out.println("---------------") ;
+        }
+
     }
 
+    static void toStream(Graph g, StreamRDF dest)
+    {
+        PrefixMapping pmap = g.getPrefixMapping() ;
+        
+        dest.start();
+        Iterator<Entry<String,String>> iterp =  pmap.getNsPrefixMap().entrySet().iterator() ;
+        for ( ; iterp.hasNext() ; )
+        {
+            Entry<String,String> e = iterp.next() ;
+            dest.prefix(e.getKey(), e.getValue()) ;
+        }
+        
+        Iterator<Triple> iter = g.find(null, null, null) ;
+        for ( ; iter.hasNext() ; )
+            dest.triple(iter.next()) ;
+        dest.finish();
+    }
     
+    static void toStream(DatasetGraph dsg, StreamRDF dest)
+    {
+        PrefixMap pmap = new PrefixMap() ;
+        pmap.putAll(dsg.getDefaultGraph().getPrefixMapping()) ;
+        Iterator<Node> gIter = dsg.listGraphNodes() ;
+        for ( ; gIter.hasNext() ; )
+        {
+            Node gn = gIter.next() ;
+            Graph g = dsg.getGraph(gn) ;
+            pmap.putAll(g.getPrefixMapping()) ;
+        }
+        
+        dest.start();
+        for ( Entry<String,IRI> e : pmap.getMapping().entrySet())
+            dest.prefix(e.getKey(), e.getValue().toString()) ;
+        
+        Iterator<Quad> iter = dsg.find(null, null, null, null) ;
+        for ( ; iter.hasNext() ; )
+            dest.quad(iter.next()) ;
+        dest.finish();
+    }
 }
 

Copied: jena/Experimental/riot-output/src/main/java/dev/PROJECT_RiotWriter.java (from r1435565, 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/dev/PROJECT_RiotWriter.java?p2=jena/Experimental/riot-output/src/main/java/dev/PROJECT_RiotWriter.java&p1=jena/Experimental/riot-output/src/main/java/riot/writer/PROJECT_RiotWriter.java&r1=1435565&r2=1436616&rev=1436616&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/writer/PROJECT_RiotWriter.java (original)
+++ jena/Experimental/riot-output/src/main/java/dev/PROJECT_RiotWriter.java Mon Jan 21 21:02:31 2013
@@ -16,26 +16,36 @@
  * limitations under the License.
  */
 
-package riot.writer;
+package dev;
+
 
 public class PROJECT_RiotWriter
 {
-    // Turtle writers:
-    // Pretty
-    // Blocks - same subject blocks, no object nesting, no lists.
-    // flat - ntriples+prefixes+numbers 
+    // Writing lists
+    //   TurtleWriter2.writeObject - apply to subject?
+    //   Also write "free lists"
+    // --> remove from heads
+    // Reduce arguments - have an output context struct
+    // Remove lists from one-connect-objects.
+    // Shared lists, included tails.
     
+    // triples(graph, null, RDF_Rest, x) => countTriples(graph, null, RDF_Rest, x)
     
-    // TODO
-    // Turtle:
-    // Order subjects to write
-    //   ==> scan by subject, not triples
+    // Check use 
 
-    // Single pass analysis
+    // Sysmetic test production.
     
-    // Lists
-    //   Do before embeddable objects because list take precedence.
+    // Should PrefixMap be String->String?
+    //   Or compile PrefixMap to a S->S map.
     
+    // Turtle writers:
+    // Pretty
+    // Blocks - same subject blocks, no object nesting, no lists.
+    // flat - ntriples+prefixes+numbers (or stream flag). 
+    // Stream
+    
+    // TODO - check.
+
     // PredicateObjectLists
     //   type to front.
     // Property order is:

Copied: jena/Experimental/riot-output/src/main/java/dev/PrintStreamRDF.java (from r1435565, jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java)
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/dev/PrintStreamRDF.java?p2=jena/Experimental/riot-output/src/main/java/dev/PrintStreamRDF.java&p1=jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java&r1=1435565&r2=1436616&rev=1436616&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java (original)
+++ jena/Experimental/riot-output/src/main/java/dev/PrintStreamRDF.java Mon Jan 21 21:02:31 2013
@@ -42,7 +42,7 @@ import com.hp.hpl.jena.sparql.core.Quad 
  *  If fed only triples, the output is valid Turtle. 
  */
 
-class PrintTurtleStreamRDF implements StreamRDF
+class PrintStreamRDF implements StreamRDF
 {
     // TODO
     // Min width for properties?
@@ -57,10 +57,16 @@ class PrintTurtleStreamRDF implements St
     // 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 static final boolean NL_GDFT_START  =  false ;      // Newline after { of dft graph
+    private static final boolean NL_GNMD_START  =  true ;       // same, but for named graphs
+    private static final boolean NL_GDFT_END    =  false ;      // Whether the closing } is on a new line
+    private static final boolean NL_GNMD_END    =  false ;      // Whether the closing } is on a new line
+    
+    private static final int INDENT_MIN_S       = 4 ;           // Range of subject indent
+    private static final int INDENT_MAX_S       = 10 ;          //   i.e. offset of predicate.
+
+    private static final int INDENT_GDFT        = 2 ;           // Default graph indent
+    private static final int INDENT_GNMD        = 4 ;           // Named graph indent
     
     private boolean lastWasTripleData = false ;
     private boolean lastWasQuadData = false ;
@@ -79,7 +85,6 @@ class PrintTurtleStreamRDF implements St
 
     private void setGraphIndent(int x)
     {
-        if ( x < INDENT_G ) x = INDENT_G ;
         currentGraphIndent = x ;
     }
 
@@ -94,7 +99,7 @@ class PrintTurtleStreamRDF implements St
     private int subjectIndent() { return currentSubjectIndent ; }
     // ----
 
-    public PrintTurtleStreamRDF(OutputStream output)
+    public PrintStreamRDF(OutputStream output)
     { 
         this.out = new IndentedWriter(output) ;
         out.setFlushOnNewline(true) ;        // Debugging
@@ -151,35 +156,7 @@ class PrintTurtleStreamRDF implements St
     {
         printPre() ;
         endGraph(g) ;
-
-        // Start graph
-        if ( lastGraph == null )
-        {
-            lastSubject = null ;
-            if ( g == Quad.defaultGraphNodeGenerated )
-            {
-                out.print("{ ") ;
-                //setGraphIndent(INDENT_G) ;
-                setGraphIndent(2) ;
-                // YUK!!!!
-                currentGraphIndent = 2 ;
-//                if ( NLAFTERGRAPH )
-//                    out.println();
-            }
-            else
-            {
-                outputNode(g) ;
-                out.print(" { ") ;
-                if ( NLAFTERGRAPH )
-                {
-                    out.println() ;
-                    setGraphIndent(INDENT_G) ;
-                }
-                else
-                    setGraphIndent(out.getCol()) ;
-            }
-            out.incIndent(graphIndent()) ;
-        }
+        startGraph(g) ;
         print$(s,p,o) ;
         lastGraph = g ;
         lastWasQuadData = true ;
@@ -195,36 +172,20 @@ class PrintTurtleStreamRDF implements St
     private void print$(Node s, Node p, Node o)
     {
         if ( equal(lastSubject, s) ) 
-        {
             out.println(" ;") ;
-            //DEBUG("[pad=%d]", lastSubjectOffset);
-            out.pad(subjectIndent()) ;
-            out.flush();
-            outputNode(p) ;
-            out.print(' ') ;
-            outputNode(o) ;
-        } else {
+        else {
             // Change subject, same graph. 
             if ( lastSubject != null )
                 endTriples() ;
             
-            int x1 = out.getCol() ;
             outputNode(s) ;
             out.print(' ') ;
-            
-            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(' ') ;
-            outputNode(o) ;
-            //out.incIndent(INDENT_S) ;
-
         }
+        out.pad(subjectIndent()) ;
+        outputNode(p) ;
+        out.print(' ') ;
+        outputNode(o) ;
         lastSubject = s ;
     }
     
@@ -259,6 +220,8 @@ class PrintTurtleStreamRDF implements St
     {
         
     }
+    
+    private boolean dftGraph() { return lastGraph == Quad.defaultGraphNodeGenerated ; }
 
     private void endGraph(Node g)
     {
@@ -268,15 +231,57 @@ class PrintTurtleStreamRDF implements St
         // End of graph
         if ( ! equal(lastGraph, g) )
         {
-            out.print(" ") ;
-            out.println(" }") ;
-            out.println() ;
-            out.decIndent(graphIndent()) ;
+            out.print(" .") ;
+            boolean nl = dftGraph() ? NL_GDFT_END : NL_GNMD_END ;
+            
+            if ( nl ) {
+                // } on a new line.
+                out.decIndent(graphIndent()) ;
+                out.println() ;
+                out.println("}") ;
+            } else {
+                // } on same line as last quad/triple.
+                out.println(" }") ;     // Trailing NL  
+                out.decIndent(graphIndent()) ;
+                out.println() ;
+            }
             lastSubject = null ;
             lastGraph = null ;
         }
     }
 
+    private void startGraph(Node g)
+    {
+        // Start graph
+        if ( lastGraph == null )
+        {
+            lastSubject = null ;
+            if ( g == Quad.defaultGraphNodeGenerated )
+            {
+                out.print("{ ") ;
+                setGraphIndent(INDENT_GDFT) ;
+                if ( NL_GDFT_START )
+                    out.println();
+            }
+            else
+            {
+                outputNode(g) ;
+                out.print(" { ") ;
+                if ( NL_GNMD_START )
+                {
+                    out.println() ;
+                    setGraphIndent(INDENT_GNMD) ;
+                }
+                else
+                {
+                    setGraphIndent(out.getCol()) ;
+                }
+            }
+            out.incIndent(graphIndent()) ;
+        }
+        lastGraph = g ;
+    }
+
     private void endTriples()
     {
         out.println(" .") ;

Modified: 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=1436616&r1=1436615&r2=1436616&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/writer/TW2.java (original)
+++ jena/Experimental/riot-output/src/main/java/riot/writer/TW2.java Mon Jan 21 21:02:31 2013
@@ -19,11 +19,15 @@
 package riot.writer;
 
 import static riot.writer.WriterConst.PREFIX_IRI ;
+import static riot.writer.WriterConst.RDF_First ;
+import static riot.writer.WriterConst.RDF_Nil ;
+import static riot.writer.WriterConst.RDF_Rest ;
 
 import java.util.* ;
 import java.util.Map.Entry ;
 
 import org.apache.jena.atlas.io.IndentedWriter ;
+import org.apache.jena.atlas.iterator.Iter ;
 import org.apache.jena.atlas.lib.Pair ;
 
 import com.hp.hpl.jena.graph.Graph ;
@@ -31,7 +35,6 @@ 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
@@ -59,60 +62,155 @@ public class TW2
     // Single, multi-function, pass over the graph 
     // It alread scans all objects.
 
-    /** Find all well-formed lists */  
-    static Set<Triple> findLists(Graph graph)
+    /** Find all list heads and all nodes in well-formed lists.
+     * Return a (list head -> Elements map), list elements)  
+     */
+    static void findLists(WriterContext cxt)
     {
+        // HashSets for use during parsing.
+        Map<Node, List<Node>> lists = new HashMap<Node, List<Node>>() ;
+        // Lists that are printed as free standing lists. 
+        Map<Node, List<Node>> freeLists = new HashMap<Node, List<Node>>() ;
+        // Lists that are shared 
+        Map<Node, List<Node>> nLinkedLists = new HashMap<Node, List<Node>>() ;
         
-        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() ;
-            // ...
+        Collection<Node> listElts = new HashSet<Node>() ;
+        List<Triple> tails = triples(cxt.graph, Node.ANY, RDF_Rest, RDF_Nil) ;
+        for ( Triple t : tails )
+        {
+            // Returns the elements, reversed.
+            Collection<Node> listElts2 = new HashSet<Node>() ;
+            Pair<Node, List<Node>> p = followTailToHead(cxt, t.getSubject(), listElts2) ;
+            if ( p != null )
+            {
+                Node headElt = p.getLeft() ; 
+                // Free standing?
+                List<Node> elts = p.getRight() ;
+                long numLinks = countTriples(cxt.graph, null, null, headElt) ;
+                if ( numLinks == 1 )
+                    lists.put(headElt, elts) ;
+                else if ( numLinks == 0 )
+                    // 0 connected lists
+                    freeLists.put(headElt, elts) ;
+                else 
+                {
+                    // Two triples to this list.
+                    // TODO Can't print the list in abbreviated form as we need to name the head.
+                    // Take out first element, print rest normally, new head is a one-connected node.
+                    //OR do in the printing. (N3 has "_:b :-")
+                    nLinkedLists.put(headElt, elts) ;
+                }
+                listElts.addAll(listElts2) ;
+            }
         }
-        tails.close();
+        cxt.freeLists = freeLists ;
+        cxt.lists = lists ;
+        cxt.listElts = listElts ;
+        cxt.nLinkedLists= nLinkedLists ; 
+    }
+//
+//    // Return is the elements
+//    static Pair<Collection<Node>, Collection<Node>>  findList1(Node lastElt, WriterContext cxt)
+//    {
+//        
+//    }
+    
+    
+    // return head elt node, list of elements.
+    private static Pair<Node, List<Node>> followTailToHead(WriterContext cxt, Node lastListElt, Collection<Node> listElts)
+    {
+        List<Node> listCells = new ArrayList<Node>() ;
+        List<Node> eltsReversed = new ArrayList<Node>() ;
+        List<Triple> acc =  new ArrayList<Triple>() ;
+        Node x = lastListElt ;
+        final Graph graph = cxt.graph ;
         
-        return null ;
+        for ( ; ; )
+        {
+            if ( ! validListElement(graph, x, acc) )
+            {
+                if ( listCells.size() == 0 )
+                    // No earlier valid list.
+                    return null ;
+                // Fix up to previous valid list cell.
+                x = listCells.remove(listCells.size()-1) ;
+                break ;
+            }
+            
+            Triple t = triple1(graph, x, RDF_First, null) ;
+            if ( t == null )
+                return null ;
+            eltsReversed.add(t.getObject()) ;
+            listCells.add(x) ;
+            
+            // Try to move up the list.
+            List<Triple> acc2 = triples(graph, null, null, x) ;
+            long numRest = countTriples(graph, null, RDF_Rest, x) ;
+            if ( numRest != 1 )
+            {
+                // Head of well-formed list.
+                // Classified by 0,1,more links later.
+                listCells.add(x) ;
+                break ;
+            }
+            // numRest == 1
+            int numLinks = acc2.size() ;
+            if ( numLinks > 1 )
+                // Non-list links to x
+                break ;
+            // Valid.
+            Triple tLink = acc2.get(0) ;
+            x = tLink.getSubject() ;
+        }
+        // Success.
+        listElts.addAll(listCells) ;
+        Collections.reverse(eltsReversed) ;
+        return Pair.create(x, eltsReversed);
+    }
+
+    /* Return the triples of the list element, or null if invalid list */
+    private static boolean validListElement(Graph graph, Node x, List<Triple> acc)
+    {
+        Triple t1 = triple1(graph, x, RDF_Rest, null) ; // Which we came up to get here :-(
+        if ( t1 == null )
+            return false ;
+        Triple t2 = triple1(graph, x, RDF_First, null) ;
+        if ( t2 == null )
+            return false ;
+        long N = countTriples(graph, x, null, null) ;
+        if ( N != 2 )
+            return false ;
+        acc.add(t1) ;
+        acc.add(t2) ;
+        return true ;
     }
 
-    
     static final boolean recordObjectMisses = true ; 
     
     /** Find all embeddable objects */  
     @SuppressWarnings("null")
-    static Pair<Set<Node>, Set<Triple>> findOneConnectedBNodeObjects(Graph graph)
+    static void findOneConnectedBNodeObjects(WriterContext cxt)
     {
-        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) ;
+
+        ExtendedIterator<Triple> iter = cxt.graph.find(Node.ANY, Node.ANY, Node.ANY) ;
+        try {
+            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(cxt.graph, obj) ;
+                if ( n != null )
+                    bNodesObj1.add(n) ;
             }
-        }
-        iter.close() ;
-        return Pair.create(bNodesObj1, triplesObj1) ;
+        } finally { iter.close() ; }
+        cxt.nestedObjects = bNodesObj1 ;
     }
 
     static Node connectedOnce(Graph graph, Node obj)
@@ -129,21 +227,55 @@ public class TW2
     
     static Collection<Triple> triplesOfSubject(Graph graph, Node subj)
     {
-        Collection<Triple> x = new HashSet<Triple>() ;
-        accTriplesOfSubject(x, graph, subj) ;
-        return x ;
+        return triples(graph, subj, Node.ANY, Node.ANY) ;
+    }
+
+    /* Get all the triples for the graph.find */
+    static List<Triple> triples(Graph graph, Node s, Node p, Node o)
+    {
+        List<Triple> acc =  new ArrayList<Triple>() ;
+        accTriples(acc, graph, s, p, o) ;
+        return acc ;
     }
 
-    static void accTriplesOfSubject(Collection<Triple> acc, Graph graph, Node subj)
+    /* Get all the triples for the graph.find */
+    private static long countTriples(Graph graph, Node s, Node p, Node o)
     {
-        ExtendedIterator<Triple> iter = graph.find(subj, Node.ANY, Node.ANY) ;
+        ExtendedIterator<Triple> iter = graph.find(s, p, o) ;
+        try { return Iter.count(iter) ; }
+        finally { iter.close() ; }
+    }
+
+    static void accTriples(Collection<Triple> acc, Graph graph, Node s, Node p, Node o)
+    {
+        ExtendedIterator<Triple> iter = graph.find(s, p, o) ;
         for ( ; iter.hasNext() ; )
             acc.add(iter.next()) ;
         iter.close() ;
     }
 
+    /* Get a triple or null. */
+    static Triple triple1(Graph graph, Node s, Node p, Node o)
+    {
+        ExtendedIterator<Triple> iter = graph.find(s, p, o) ;
+        try {
+            if ( ! iter.hasNext() )
+                return null ;
+            Triple t = iter.next() ;
+            if (  iter.hasNext() )
+                return null ;
+            return t ;
+        } finally { iter.close() ; }
+    }
+
     static void writeNode(IndentedWriter out, Node node, Map<String, String> prefixMap)
     {
+        if ( RDF_Nil.equals(node))
+        {
+            print(out, "()") ;
+            return ;
+        } 
+        
         // See RIOT NodeFormatter
         if ( node.isURI() )
         {

Added: jena/Experimental/riot-output/src/main/java/riot/writer/TestRIOTWriter.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/writer/TestRIOTWriter.java?rev=1436616&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/writer/TestRIOTWriter.java (added)
+++ jena/Experimental/riot-output/src/main/java/riot/writer/TestRIOTWriter.java Mon Jan 21 21:02:31 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.ByteArrayInputStream ;
+import java.io.ByteArrayOutputStream ;
+import java.io.IOException ;
+
+import org.apache.jena.atlas.io.IO ;
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.riot.Lang ;
+import org.apache.jena.riot.RDFDataMgr ;
+import org.junit.Test ;
+
+import com.hp.hpl.jena.rdf.model.Model ;
+import com.hp.hpl.jena.rdf.model.ModelFactory ;
+import com.hp.hpl.jena.util.FileUtils ;
+
+public class TestRIOTWriter extends BaseTest
+{
+    // Round trip tests.
+    
+    static String DIR = "testing/RIOT/Writer" ;
+
+    @Test public void writer00() { test("writer-rt-00.ttl") ; }
+    @Test public void writer01() { test("writer-rt-01.ttl") ; }
+    @Test public void writer02() { test("writer-rt-02.ttl") ; }
+    @Test public void writer03() { test("writer-rt-03.ttl") ; }
+    @Test public void writer04() { test("writer-rt-04.ttl") ; }
+    @Test public void writer05() { test("writer-rt-05.ttl") ; }
+    @Test public void writer06() { test("writer-rt-06.ttl") ; }
+    @Test public void writer07() { test("writer-rt-07.ttl") ; }
+    @Test public void writer08() { test("writer-rt-08.ttl") ; }
+    @Test public void writer09() { test("writer-rt-09.ttl") ; }
+    @Test public void writer10() { test("writer-rt-10.ttl") ; }
+
+    private void test(String filename)
+    {
+        String fn = DIR + "/" + filename ;
+        Model m = RDFDataMgr.loadModel(fn) ;
+        
+        // check.
+        ByteArrayOutputStream out = new ByteArrayOutputStream() ;
+        TurtleWriter2.write(out, m) ;
+        ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()) ;
+        
+        Model m2 = ModelFactory.createDefaultModel() ;
+        RDFDataMgr.read(m2, in, Lang.TURTLE) ;
+        boolean b = m.isIsomorphicWith(m2) ;
+        if ( !b )
+        {
+            try { 
+                System.out.println("---------------------------------------------------------") ;
+                System.out.println("#### file="+filename) ;
+                String s = FileUtils.readWholeFileAsUTF8(fn) ;
+                System.out.print(s) ;
+            } catch ( IOException ex) { IO.exception(ex) ; }
+        }
+        
+        assertTrue("file="+filename,  b) ; 
+    }
+    
+}
+

Modified: 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=1436616&r1=1436615&r2=1436616&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriter2.java (original)
+++ jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriter2.java Mon Jan 21 21:02:31 2013
@@ -19,12 +19,20 @@
 package riot.writer;
 
 import static riot.writer.WriterConst.* ;
+import static riot.writer.WriterConst.INDENT_PREDICATE ;
+import static riot.writer.WriterConst.LONG_PREDICATE ;
+import static riot.writer.WriterConst.LONG_SUBJECT ;
+import static riot.writer.WriterConst.MIN_GAP ;
+import static riot.writer.WriterConst.iriType ;
+import static riot.writer.WriterConst.rdfNS ;
 
 import java.io.OutputStream ;
-import java.util.* ;
+import java.util.Collection ;
+import java.util.Iterator ;
+import java.util.List ;
+import java.util.Map ;
 
 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 ;
@@ -59,13 +67,21 @@ public class TurtleWriter2
     // Call from TriG as well.
     static void write$(IndentedWriter out, Graph graph, Map<String, String> prefixMap)
     {
+        WriterContext cxt = new WriterContext() ;
+        cxt.prefixMap = prefixMap ;
+        cxt.graph = graph ;
+
+        // TW2 -> hereas 
+        
         // Configuration.
-        Pair<Set<Node>, Set<Triple>> p = TW2.findOneConnectedBNodeObjects(graph) ;
-        Set<Node> bNodesObj1 = p.getLeft() ;
-        Set<Triple> triplesObj1 = p.getRight() ;
+        TW2.findOneConnectedBNodeObjects(cxt) ;
         
         // Lists
+        TW2.findLists(cxt) ;
         
+        // TODO Right check?
+        // Stop head of lists printed as triples going all the way to the good part. 
+        cxt.nestedObjects.removeAll(cxt.listElts) ;
         
         // Prefixes
         TW2.writePrefixes(out, prefixMap) ;
@@ -74,36 +90,91 @@ public class TurtleWriter2
 
         // Or - listSubjects and sort.
         Iterator<Node> subjects = GLib.listSubjects(graph) ;
-        writeBySubject(out, graph, subjects, bNodesObj1, triplesObj1, new HashSet<Object>(), prefixMap) ;
+        boolean b = writeBySubject(out, subjects, cxt) ;
+        
+        if ( ! cxt.nLinkedLists.isEmpty() )
+        {
+            // Print carefully - need a label for the first cell.
+            // So we write out the first element of the list in triples, then put
+            // the remainer as a pretty lst.
+            
+            if ( b ) out.println() ;
+            b = false ;
+            
+            for ( Node n : cxt.nLinkedLists.keySet() )
+            {
+                
+                
+                List<Node> x = cxt.nLinkedLists.get(n) ;
+                
+                // ---- DRY : writeCluster
+                TW2.writeNode(out, n, cxt.prefixMap) ;
+                
+                if ( out.getCol() > LONG_SUBJECT )
+                    println(out) ;
+                else
+                    gap(out) ;
+                out.incIndent(INDENT_PREDICATE) ;
+                // ----
+                out.pad() ;
+                TW2.writeNode(out, RDF_First, cxt.prefixMap) ;
+                TW2.print(out, " ") ;
+                TW2.writeNode(out, x.get(0), cxt.prefixMap) ;
+                TW2.print(out, " ;") ;
+                println(out) ;
+                TW2.writeNode(out, RDF_Rest, cxt.prefixMap) ;
+                TW2.print(out, "  ") ;
+                x = x.subList(1, x.size()) ;
+                list(out, x, cxt) ;
+                TW2.print(out, " .") ;
+                println(out) ; 
+            }
+        }
+        //else out.println("# No NNNN") ;
+        
+        if ( ! cxt.freeLists.isEmpty() )
+        {
+            if ( b ) out.println() ;
+            out.println("# >> 0000") ;
+            // Write free lists.
+            for ( Node n : cxt.freeLists.keySet() )
+            {
+                list(out, cxt.freeLists.get(n), cxt) ;
+                out.println(" .") ;
+            }
+            //out.println() ;
+        }
+        //else out.println("# No 0000") ;
     }
     
-    static void writeBySubject(IndentedWriter out, Graph graph, 
-                               Iterator<Node> subjects, 
-                               Collection<Node> nestedObjects, Collection<Triple> skip, 
-                               Collection<Object> lists, 
-                               Map<String, String> prefixMap)
+    // return true if did write something.
+    static boolean writeBySubject(IndentedWriter out, Iterator<Node> subjects, WriterContext cxt)
     {
+        boolean first = true ;
         for ( ; subjects.hasNext() ; )
         {
             Node subj = subjects.next() ;
-            if ( nestedObjects.contains(subj) )
+            if ( cxt.nestedObjects.contains(subj) )
                 continue ;
+            if ( cxt.listElts.contains(subj) )
+                continue ;
+            if ( ! first ) 
+                out.println() ;
+            first = false ;
             
-            Collection<Triple> cluster = TW2.triplesOfSubject(graph, subj) ;
-            writeCluster(out, graph, subj, cluster, nestedObjects, prefixMap) ;
+            Collection<Triple> cluster = TW2.triplesOfSubject(cxt.graph, subj) ;
+            writeCluster(out, subj, cluster, cxt) ;
         }
+        return !first ;
     }
     
     
     // 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)
+    static void writeCluster(IndentedWriter out, Node subject, Collection<Triple> cluster, WriterContext cxt)
     {
-        //int OFFSET = out.getIndent() ;
-        
         if ( cluster.isEmpty() ) return ;
-        TW2.writeNode(out, subject, prefixMap) ;
+        TW2.writeNode(out, subject, cxt.prefixMap) ;
         
         if ( out.getCol() > LONG_SUBJECT )
             println(out) ;
@@ -111,17 +182,15 @@ public class TurtleWriter2
             gap(out) ;
         out.incIndent(INDENT_PREDICATE) ;
         out.pad() ;
-        writePredicateObjectList(out, graph, cluster, nestedObjects, prefixMap) ;
+        writePredicateObjectList(out, cluster, cxt) ;
         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)
+    private static void writePredicateObjectList(IndentedWriter out, Collection<Triple> cluster, WriterContext cxt)
     {
         boolean first = true ;
         // Calc columns
@@ -147,12 +216,12 @@ public class TurtleWriter2
             // Write predicate.
             int colPredicateStart = out.getCol() ;
             
-            if ( ! prefixMap.containsValue(rdfNS) &&
+            if ( ! cxt.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) ;
+                TW2.writeNode(out, triple.getPredicate(), cxt.prefixMap) ;
             int colPredicateFinish = out.getCol() ;
             int wPredicate = (colPredicateFinish-colPredicateStart) ;
             
@@ -166,18 +235,26 @@ public class TurtleWriter2
             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) ;
+            writeObject(out, obj, cxt) ;
             out.decIndent(INDENT_OBJECT) ;
         }
     }
     
-    private static void nestedObject(IndentedWriter out, Graph graph, Node obj,
-                                     Collection<Node> nestedObjects, Map<String, String> prefixMap)
+    // --> write S or O??
+    private static void writeObject(IndentedWriter out, Node obj, WriterContext cxt)
+    {
+        // Order matters? - one connected objects may include list elements.
+        if ( cxt.lists.containsKey(obj) )
+            list(out, cxt.lists.get(obj), cxt) ; 
+        else if ( cxt.nestedObjects.contains(obj) )
+            nestedObject(out, obj, cxt) ;
+        else
+            TW2.writeNode(out, obj, cxt.prefixMap) ;
+    }
+
+    private static void nestedObject(IndentedWriter out, Node obj, WriterContext cxt)
     {
-        Collection<Triple> x = TW2.triplesOfSubject(graph, obj) ;
+        Collection<Triple> x = TW2.triplesOfSubject(cxt.graph, obj) ;
         
         if ( x.isEmpty() )
         {
@@ -189,7 +266,7 @@ public class TurtleWriter2
         {
             TW2.print(out, "[ ") ;
             // Includes nested object in triple.
-            writePredicateObjectList(out, graph, x, nestedObjects, prefixMap) ;
+            writePredicateObjectList(out, x, cxt) ;
             TW2.print(out, " ]") ;
             return ;
         }
@@ -201,7 +278,7 @@ public class TurtleWriter2
         out.setAbsoluteIndent(here) ;
         // Inline: println(out) ;
         out.incIndent(2) ;
-        writePredicateObjectList(out, graph, x, nestedObjects, prefixMap) ;
+        writePredicateObjectList(out, x, cxt) ;
         out.decIndent(2) ;
         if ( true )
         {
@@ -216,14 +293,26 @@ public class TurtleWriter2
     }
     
      
+    private static void list(IndentedWriter out, List<Node> elts, WriterContext cxt)
+    {
+        TW2.print(out, "(") ;
+        for ( Node n : elts )
+        {
+            TW2.print(out, " ") ;
+            writeObject(out, n, cxt) ;
+        }
+
+        TW2.print(out, " )") ;
+    }
     
-    // flush aggressively (debugging)
     
+
     private static void gap(IndentedWriter out)
     {
         out.print(' ', MIN_GAP) ;
     }
     
+    // flush aggressively (debugging)
     private static void println(IndentedWriter out)
     {
         out.println() ;

Modified: 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=1436616&r1=1436615&r2=1436616&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriterBlocks.java (original)
+++ jena/Experimental/riot-output/src/main/java/riot/writer/TurtleWriterBlocks.java Mon Jan 21 21:02:31 2013
@@ -65,7 +65,16 @@ public class TurtleWriterBlocks
         Collection<Node> nestedObjects = Collections.emptyList() ; 
         Collection<Triple> skip = Collections.emptyList() ;
         Collection<Object> lists = Collections.emptyList() ;
+        
+        WriterContext cxt = new WriterContext() ;
+        cxt.graph = graph ;
+        cxt.nestedObjects = Collections.emptySet() ;
+        cxt.lists = Collections.emptyMap() ;
+        cxt.freeLists = Collections.emptyMap() ;
+        cxt.listElts  = Collections.emptyList() ;
+        cxt.prefixMap = prefixMap ;
             
+        // See PrintStreamRDF
         PeekIterator<Triple> stream = PeekIterator.create(triples) ;
         List<Triple> cluster = new ArrayList<Triple>() ;
         Node subject = null ;
@@ -90,7 +99,7 @@ public class TurtleWriterBlocks
             }
             if ( subject != null )
             {
-                TurtleWriter2.writeCluster(out, graph, subject, cluster, nestedObjects, prefixMap) ;
+                TurtleWriter2.writeCluster(out, subject, cluster, cxt) ;
                 subject = null ;
             }
             else 

Modified: 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=1436616&r1=1436615&r2=1436616&view=diff
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/writer/WriterConst.java (original)
+++ jena/Experimental/riot-output/src/main/java/riot/writer/WriterConst.java Mon Jan 21 21:02:31 2013
@@ -18,6 +18,7 @@
 
 package riot.writer;
 
+import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.vocabulary.RDF ;
 
 public class WriterConst
@@ -26,6 +27,10 @@ public class WriterConst
     public static final int LONG_PREDICATE = 30 ;
     public static final int PREFIX_IRI = 15;
     
+    public static final Node RDF_First = RDF.Nodes.first ;
+    public static final Node RDF_Rest = RDF.Nodes.rest ;
+    public static final Node RDF_Nil = RDF.Nodes.nil ;
+    
     // Column widths.
     public static int COLW_SUBJECT = 6 ;
     public static int COLW_PREDICATE = 8 ;

Added: jena/Experimental/riot-output/src/main/java/riot/writer/WriterContext.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/riot/writer/WriterContext.java?rev=1436616&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/riot/writer/WriterContext.java (added)
+++ jena/Experimental/riot-output/src/main/java/riot/writer/WriterContext.java Mon Jan 21 21:02:31 2013
@@ -0,0 +1,38 @@
+/**
+ * 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.util.Collection ;
+import java.util.List ;
+import java.util.Map ;
+import java.util.Set ;
+
+import com.hp.hpl.jena.graph.Graph ;
+import com.hp.hpl.jena.graph.Node ;
+
+final class WriterContext
+{
+    Graph graph ;
+    Set<Node> nestedObjects = null ;           // Blank nodes that have one incoming triple
+    Map<Node, List<Node>> lists = null;        // The head node in each well-formed lists -> list elements 
+    Map<Node, List<Node>> freeLists = null;    // List that do not have any incoming triples 
+    Map<Node, List<Node>> nLinkedLists = null; // Lists that have more than one incoming triple 
+    Collection<Node> listElts  = null;         // All nodes that are part of list structures.
+    Map<String, String> prefixMap ;
+}

Added: jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-00.ttl
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-00.ttl?rev=1436616&view=auto
==============================================================================
--- jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-00.ttl (added)
+++ jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-00.ttl Mon Jan 21 21:02:31 2013
@@ -0,0 +1 @@
+# Empty.

Added: jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-01.ttl
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-01.ttl?rev=1436616&view=auto
==============================================================================
--- jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-01.ttl (added)
+++ jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-01.ttl Mon Jan 21 21:02:31 2013
@@ -0,0 +1,5 @@
+@prefix :     <http://example/> .
+@prefix ns:   <http://example/ns#> .
+@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
+
+# Empty.

Added: jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-02.ttl
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-02.ttl?rev=1436616&view=auto
==============================================================================
--- jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-02.ttl (added)
+++ jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-02.ttl Mon Jan 21 21:02:31 2013
@@ -0,0 +1,8 @@
+@prefix :     <http://example/> .
+@prefix ns:   <http://example/ns#> .
+@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
+
+:s ns:p1 <http://other/planet> .
+:s ns:p2 123 .
+:s ns:p3 [] .
+:s a :T .

Added: jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-03.ttl
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-03.ttl?rev=1436616&view=auto
==============================================================================
--- jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-03.ttl (added)
+++ jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-03.ttl Mon Jan 21 21:02:31 2013
@@ -0,0 +1,6 @@
+@prefix :     <http://example/> .
+@prefix ns:   <http://example/ns#> .
+@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
+
+:z :p1 _:a .
+:z :p2 _:a .

Added: jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-04.ttl
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-04.ttl?rev=1436616&view=auto
==============================================================================
--- jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-04.ttl (added)
+++ jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-04.ttl Mon Jan 21 21:02:31 2013
@@ -0,0 +1,8 @@
+@prefix :     <http://example/> .
+@prefix ns:   <http://example/ns#> .
+@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
+
+:a :q1 (1 2 3) .
+:a :q2 ( 1 ) .
+:a :q3 () .
+:a :q4 ( :s [ :p :o ] ) .

Added: jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-05.ttl
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-05.ttl?rev=1436616&view=auto
==============================================================================
--- jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-05.ttl (added)
+++ jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-05.ttl Mon Jan 21 21:02:31 2013
@@ -0,0 +1,10 @@
+@prefix :     <http://example/> .
+@prefix ns:   <http://example/ns#> .
+@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
+
+# Shared list.
+:s1 :p _:b .
+:s2 :p _:b .
+
+ _:b rdf:first 9 ;
+     rdf:rest ( 8 ) .

Added: jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-06.ttl
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-06.ttl?rev=1436616&view=auto
==============================================================================
--- jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-06.ttl (added)
+++ jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-06.ttl Mon Jan 21 21:02:31 2013
@@ -0,0 +1,16 @@
+@prefix :     <http://example/> .
+@prefix ns:   <http://example/ns#> .
+@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
+
+# Shared tail.
+:s1 :stail _:x1 .
+:s2 :stail _:x2 .
+
+_:x1 rdf:first "A" ;
+    rdf:rest _:y .
+
+_:x2 rdf:first "B" ;
+    rdf:rest _:y .
+
+_:y rdf:first 9 ;
+    rdf:rest ( 8 7 ) .

Added: jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-07.ttl
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-07.ttl?rev=1436616&view=auto
==============================================================================
--- jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-07.ttl (added)
+++ jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-07.ttl Mon Jan 21 21:02:31 2013
@@ -0,0 +1,9 @@
+@prefix :     <http://example/> .
+@prefix ns:   <http://example/ns#> .
+@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
+
+# bad list
+:x :p1 _:bad1 .
+_:bad1 rdf:first 19 ;
+    rdf:first 18 ;
+    rdf:rest rdf:nil .

Added: jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-08.ttl
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-08.ttl?rev=1436616&view=auto
==============================================================================
--- jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-08.ttl (added)
+++ jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-08.ttl Mon Jan 21 21:02:31 2013
@@ -0,0 +1,9 @@
+@prefix :     <http://example/> .
+@prefix ns:   <http://example/ns#> .
+@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
+
+# bad list
+:x :p2 _:bad2 .
+
+_:bad2 rdf:first 29 ;
+    rdf:rest 3 .

Added: jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-09.ttl
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-09.ttl?rev=1436616&view=auto
==============================================================================
--- jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-09.ttl (added)
+++ jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-09.ttl Mon Jan 21 21:02:31 2013
@@ -0,0 +1,8 @@
+@prefix :     <http://example/> .
+@prefix ns:   <http://example/ns#> .
+@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
+
+# bad list
+:x :p3 _:bad .
+
+_:bad rdf:rest (1 2 3) .

Added: jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-10.ttl
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-10.ttl?rev=1436616&view=auto
==============================================================================
--- jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-10.ttl (added)
+++ jena/Experimental/riot-output/testing/RIOT/Writer/writer-rt-10.ttl Mon Jan 21 21:02:31 2013
@@ -0,0 +1,10 @@
+@prefix :     <http://example/> .
+@prefix ns:   <http://example/ns#> .
+@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
+
+:x :p _:bad1 .
+
+_:bad1  rdf:first 39 ;
+        rdf:rest _:bad2 .
+
+_:bad2 rdf:rest (38 37 36) .