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 2017/06/20 10:44:21 UTC

[1/6] jena git commit: General tidying up.

Repository: jena
Updated Branches:
  refs/heads/master 887def848 -> f89025a83


General tidying up.

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

Branch: refs/heads/master
Commit: bb7af3b4d1a7a11c1b48a31917d17c96d1291109
Parents: fbd93e3
Author: Andy Seaborne <an...@apache.org>
Authored: Sat Jun 17 15:41:23 2017 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sat Jun 17 15:41:23 2017 +0100

----------------------------------------------------------------------
 .../org/apache/jena/riot/system/RiotLib.java    |  2 +-
 .../apache/jena/riot/writer/TurtleShell.java    |  2 +-
 .../apache/jena/sparql/util/graph/Findable.java | 19 +++++-
 .../sparql/util/graph/FindableCollection.java   | 68 ++++++++++++++++++++
 .../apache/jena/sparql/util/graph/GNode.java    |  8 ++-
 5 files changed, 94 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/bb7af3b4/jena-arq/src/main/java/org/apache/jena/riot/system/RiotLib.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/system/RiotLib.java b/jena-arq/src/main/java/org/apache/jena/riot/system/RiotLib.java
index e06300e..637a640 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/system/RiotLib.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/system/RiotLib.java
@@ -101,7 +101,7 @@ public class RiotLib
         return fixupPrefixIRI(prefix+":"+localPart);
     }
 
-    /** Convert an prefix name (qname) to an IRI, for when the prerix is nor defined.
+    /** Convert an prefix name (qname) to an IRI, for when the prefix is not defined.
      * @see ARQ#fixupUndefinedPrefixes
      */
     public static String fixupPrefixIRI(String prefixedName) {

http://git-wip-us.apache.org/repos/asf/jena/blob/bb7af3b4/jena-arq/src/main/java/org/apache/jena/riot/writer/TurtleShell.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/writer/TurtleShell.java b/jena-arq/src/main/java/org/apache/jena/riot/writer/TurtleShell.java
index a40cf6d..c820bb8 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/writer/TurtleShell.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/writer/TurtleShell.java
@@ -121,7 +121,7 @@ public abstract class TurtleShell {
         private final Set<Node>             freeBnodes ;  
 
         // The head node in each well-formed list -> list elements
-        private /*final*/ Map<Node, List<Node>> lists ;   
+        private final Map<Node, List<Node>> lists ;   
 
         // List that do not have any incoming triples
         private final Map<Node, List<Node>> freeLists ; 

http://git-wip-us.apache.org/repos/asf/jena/blob/bb7af3b4/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/Findable.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/Findable.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/Findable.java
index 95c9435..08275fa 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/Findable.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/Findable.java
@@ -20,11 +20,26 @@ package org.apache.jena.sparql.util.graph;
 
 import java.util.Iterator ;
 
+import org.apache.jena.atlas.iterator.Iter;
 import org.apache.jena.graph.Node ;
 import org.apache.jena.graph.Triple ;
 
+/** Minimal interface to find by pattern */
 public interface Findable
 {
-    public Iterator<Triple> find(Node s, Node p, Node o) ; 
-    public boolean  contains(Node s, Node p, Node o) ; 
+    /** Return an iterator over all triples matching the {@code (s,p,o)} pattern. 
+     * Each element of {@code (s,p,o)} can be concrete, or the wildcard {@code Node.ANY}. 
+     */  
+    public Iterator<Triple> find(Node s, Node p, Node o) ;
+    
+    /** Return whether any triple matches the (s,p,o) pattern. 
+     * Each element of {@code (s,p,o)} can be concrete, or the wildcard {@code Node.ANY}. 
+     */  
+    public boolean contains(Node s, Node p, Node o) ;
+    
+    /** Return the number of triples matching the (s,p,o) pattern. 
+     */  
+    public default int count(Node s, Node p, Node o) {
+        return (int)Iter.count(find(s,p,o));
+    }
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/bb7af3b4/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/FindableCollection.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/FindableCollection.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/FindableCollection.java
new file mode 100644
index 0000000..2a85439
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/FindableCollection.java
@@ -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 org.apache.jena.sparql.util.graph;
+
+import java.util.*;
+
+import org.apache.jena.atlas.iterator.Iter;
+import org.apache.jena.graph.Node ;
+import org.apache.jena.graph.Triple ;
+
+public class FindableCollection implements Findable
+{
+    private Collection<Triple> triples ;
+
+    public FindableCollection(Collection<Triple> triples) { this.triples = triples ; }
+    
+    @Override
+    public Iterator<Triple> find(Node _s, Node _p, Node _o) {
+        Node s = m(_s) ;
+        Node p = m(_p) ;
+        Node o = m(_o) ;
+        return Iter.filter(triples.iterator(), (t)->matches(t, s, p, o)); 
+    }
+    
+    static Node m(Node n) {
+        return n == Node.ANY ? null : n ; 
+    }
+    
+    // Does concrete t match the pattern (s,p,o)?
+    /*package*/ static boolean matches(Triple t, Node s, Node p, Node o) {
+        if ( s != null && ! Objects.equals(s, t.getSubject()) )
+            return false ;
+        if ( p != null && ! Objects.equals(p, t.getPredicate()) )
+            return false ;
+        if ( o != null && ! Objects.equals(o, t.getObject()) )
+            return false ;
+        return true ;
+    }
+    
+    @Override
+    public boolean contains(Node s, Node p, Node o)
+    {
+        if ( s == Node.ANY ) s = null ;
+        if ( p == Node.ANY ) p = null ;
+        if ( o == Node.ANY ) o = null ;
+        for ( Triple t : triples ) {
+            if ( matches(t, s, p, o) )
+                return true;
+        }
+        return false ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/bb7af3b4/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/GNode.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/GNode.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/GNode.java
index d278d47..983f0cd 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/GNode.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/GNode.java
@@ -18,8 +18,11 @@
 
 package org.apache.jena.sparql.util.graph;
 
+import java.util.Collection;
+
 import org.apache.jena.graph.Graph ;
 import org.apache.jena.graph.Node ;
+import org.apache.jena.graph.Triple;
 import org.apache.jena.sparql.core.BasicPattern ;
 
 
@@ -32,8 +35,11 @@ public class GNode
     { this.findable = new FindableGraph(graph) ; this.node = node ; }
     
     public GNode(BasicPattern triples, Node node)
-    { this.findable = new FindableBasicPattern(triples) ; this.node = node ; }
+    { this.findable = new FindableCollection(triples.getList()) ; this.node = node ; }
     
+    public GNode(Collection<Triple> triples, Node node)
+    { this.findable = new FindableCollection(triples) ; this.node = node ; }
+
     public GNode(GNode other, Node node)
     { this.findable = other.findable ; this.node = node ; }
 


[3/6] jena git commit: Support --fixup of prefix names.

Posted by an...@apache.org.
Support --fixup of prefix names.

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

Branch: refs/heads/master
Commit: 78217659c3a4185a06cc0ef69b3ef6093fcb6c0d
Parents: d377dd1
Author: Andy Seaborne <an...@apache.org>
Authored: Sat Jun 17 15:45:20 2017 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sat Jun 17 15:45:20 2017 +0100

----------------------------------------------------------------------
 jena-cmds/src/main/java/arq/uparse.java | 70 ++++++++++++++++++++++------
 1 file changed, 57 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/78217659/jena-cmds/src/main/java/arq/uparse.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/main/java/arq/uparse.java b/jena-cmds/src/main/java/arq/uparse.java
index 83d44cb..22290b5 100644
--- a/jena-cmds/src/main/java/arq/uparse.java
+++ b/jena-cmds/src/main/java/arq/uparse.java
@@ -21,25 +21,30 @@ package arq;
 import java.io.IOException ;
 import java.util.List ;
 
+import arq.cmdline.CmdARQ ;
 import jena.cmd.ArgDecl;
 import jena.cmd.CmdException;
-
 import org.apache.jena.atlas.io.IndentedLineBuffer ;
 import org.apache.jena.atlas.lib.Lib ;
+import org.apache.jena.atlas.logging.LogCtl ;
+import org.apache.jena.query.ARQ ;
+import org.apache.jena.query.QueryException ;
 import org.apache.jena.query.QueryParseException ;
 import org.apache.jena.query.Syntax ;
+import org.apache.jena.sparql.core.QueryCheckException ;
+import org.apache.jena.sparql.lang.ParserBase ;
 import org.apache.jena.sparql.modify.request.UpdateWriter ;
 import org.apache.jena.update.UpdateFactory ;
 import org.apache.jena.update.UpdateRequest ;
 import org.apache.jena.util.FileUtils ;
 
-import arq.cmdline.CmdARQ ;
-
 public class uparse extends CmdARQ
 {
     protected static final ArgDecl fileArg          = new ArgDecl(ArgDecl.HasValue, "file", "update") ;
     protected static final ArgDecl syntaxArg        = new ArgDecl(ArgDecl.HasValue, "syntax", "syn") ;
     protected static final ArgDecl argDeclPrint     = new ArgDecl(ArgDecl.HasValue, "print") ;
+    protected static final ArgDecl argDeclFixup     = new ArgDecl(ArgDecl.NoValue, "fixup") ;
+
     List<String> requestFiles = null ;
     protected Syntax updateSyntax = null ;
     private boolean printUpdate = false ;
@@ -54,6 +59,7 @@ public class uparse extends CmdARQ
         super.add(fileArg, "--file=FILE",  "Update commands to parse") ;
         super.add(syntaxArg, "--syntax=name", "Update syntax") ;
         super.add(argDeclPrint, "--print", "Print in various forms [update, none]") ;
+        super.add(argDeclFixup, "--fixup", "Convert undeclared prefix names to URIs") ;
     }
 
     @Override
@@ -63,6 +69,10 @@ public class uparse extends CmdARQ
         super.processModulesAndArgs() ;
         if ( super.cmdStrictMode )
             updateSyntax = Syntax.syntaxSPARQL_11 ;
+        
+        if ( contains(argDeclFixup) )
+            // Fixup undeclared prefix names.
+            ARQ.set(ARQ.fixupUndefinedPrefixes, true);
 
         // Set syntax
         if ( super.contains(syntaxArg) ) {
@@ -86,7 +96,6 @@ public class uparse extends CmdARQ
         
         if ( !printUpdate && ! printNone )
             printUpdate = true ;
-        
     }
     
     @Override
@@ -156,24 +165,59 @@ public class uparse extends CmdARQ
         if ( printNone )
             return ;
         
-        // And some checking.
+
+        try {
+            LogCtl.disable(ParserBase.ParserLoggerName) ;
+            checkUpdate(req, syntax);
+        } catch (UpdateCheckException ex)
+        {
+            System.err.println() ;
+            System.err.println("**** Check failure: "+ex.getMessage()) ;
+            if ( ex.getCause() != null )
+                ex.getCause().printStackTrace(System.err) ;
+        }
+        finally { LogCtl.setLevel(ParserBase.ParserLoggerName, "INFO") ; }
+    }
+    
+    public static class UpdateCheckException extends QueryException
+    {
+        public UpdateCheckException() { super() ; }
+        public UpdateCheckException(Throwable cause) { super(cause) ; }
+        public UpdateCheckException(String msg) { super(msg) ; }
+        public UpdateCheckException(String msg, Throwable cause) { super(msg, cause) ; }
+    }
+
+    
+    public static void checkUpdate(UpdateRequest req, Syntax syntax)
+    {
         IndentedLineBuffer w = new IndentedLineBuffer() ;
         UpdateWriter.output(req, w) ;
         String updateString2 = w.asString() ;
-        UpdateRequest req2 = null ;
+        
+        UpdateRequest req2;
         try {
+            String baseURI = null ;
+            if ( ! req.explicitlySetBaseURI() )
+                baseURI = req.getBaseURI() ;
             req2 = UpdateFactory.create(updateString2, syntax) ;
-        } catch (QueryParseException ex)
+        } catch (UnsupportedOperationException ex)
         {
-            System.err.println("Can not reparse update after serialization") ;
-            System.err.println(updateString2) ; 
+            // No parser after all.
+            return ;
+        }
+        catch (QueryException ex)
+        {
+            System.err.println(updateString2) ;
+            throw new QueryCheckException("could not parse output update request", ex) ;
         }
-
-        if ( ! req.equalTo(req2) )
-            System.err.println("Reparsed update does not .equalTo original parsed request") ;
-        
         
+//        if ( req.hashCode() != req2.hashCode() )
+//            throw new UpdateCheckException("reparsed query hashCode does not equal parsed input update \nUpdate (hashCode: " + req.hashCode() + ")=\n" + req + "\n\nUpdate2 (hashCode: " + req2.hashCode() + ")=\n" + req2) ;
+//        
+//        if ( ! req.equals(req2) ) 
+//            throw new UpdateCheckException("reparsed output does not equal parsed input") ;
     }
+
     
     static final String divider = "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" ;
     //static final String divider = "" ;


[6/6] jena git commit: JENA-1361, JENA-369: Merge commit 'refs/pull/263/head' of github.com:apache/jena

Posted by an...@apache.org.
JENA-1361, JENA-369: Merge commit 'refs/pull/263/head' of github.com:apache/jena

This closes #263.


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

Branch: refs/heads/master
Commit: f89025a832aa8f854f0cee012be560b550c11ffd
Parents: 887def8 f19d8b2
Author: Andy Seaborne <an...@apache.org>
Authored: Tue Jun 20 11:42:47 2017 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Tue Jun 20 11:42:47 2017 +0100

----------------------------------------------------------------------
 .../org/apache/jena/riot/system/RiotLib.java    |   2 +-
 .../apache/jena/riot/writer/TurtleShell.java    |   2 +-
 .../sparql/modify/request/UpdateWriter.java     |   2 +
 .../modify/request/UpdateWriterVisitor.java     |  10 +-
 .../jena/sparql/serializer/FmtEltLib.java       | 195 ++++++
 .../sparql/serializer/FormatterElement.java     | 688 ++++++++++---------
 .../sparql/serializer/TriplesListBlock.java     |  43 ++
 .../apache/jena/sparql/util/graph/Findable.java |  19 +-
 .../sparql/util/graph/FindableBasicPattern.java |  89 ---
 .../sparql/util/graph/FindableCollection.java   |  68 ++
 .../apache/jena/sparql/util/graph/GNode.java    |   8 +-
 jena-cmds/src/main/java/arq/uparse.java         |  70 +-
 12 files changed, 771 insertions(+), 425 deletions(-)
----------------------------------------------------------------------



[4/6] jena git commit: Tidy up.

Posted by an...@apache.org.
Tidy up.

Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/9a3a072e
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/9a3a072e
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/9a3a072e

Branch: refs/heads/master
Commit: 9a3a072e14203e2a6712bfc2444cf94538f49e92
Parents: 7821765
Author: Andy Seaborne <an...@apache.org>
Authored: Sat Jun 17 15:45:36 2017 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sat Jun 17 15:45:36 2017 +0100

----------------------------------------------------------------------
 .../sparql/util/graph/FindableBasicPattern.java | 89 --------------------
 1 file changed, 89 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/9a3a072e/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/FindableBasicPattern.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/FindableBasicPattern.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/FindableBasicPattern.java
deleted file mode 100644
index a421ca9..0000000
--- a/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/FindableBasicPattern.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.jena.sparql.util.graph;
-
-import java.util.ArrayList ;
-import java.util.Iterator ;
-import java.util.List ;
-
-import org.apache.jena.graph.Node ;
-import org.apache.jena.graph.Triple ;
-import org.apache.jena.sparql.core.BasicPattern ;
-
-
-
-
-class FindableBasicPattern implements Findable
-{
-    private BasicPattern triples ;
-
-    FindableBasicPattern(BasicPattern triples) { this.triples = triples ; }
-
-    @Override
-    public Iterator<Triple> find(Node s, Node p, Node o)
-    {
-        if ( s == Node.ANY ) s = null ;
-        if ( p == Node.ANY ) p = null ;
-        if ( o == Node.ANY ) o = null ;
-        
-        List<Triple> r = new ArrayList<>() ;
-        for ( Triple t : triples )
-        {
-            if ( s != null && !t.getSubject().equals( s ) )
-            {
-                continue;
-            }
-            if ( p != null && !t.getPredicate().equals( p ) )
-            {
-                continue;
-            }
-            if ( o != null && !t.getObject().equals( o ) )
-            {
-                continue;
-            }
-            r.add( t );
-        }
-        return r.iterator() ;
-    }
-    
-    @Override
-    public boolean contains(Node s, Node p, Node o)
-    {
-        if ( s == Node.ANY ) s = null ;
-        if ( p == Node.ANY ) p = null ;
-        if ( o == Node.ANY ) o = null ;
-        for ( Triple t : triples )
-        {
-            if ( s != null && !t.getSubject().equals( s ) )
-            {
-                continue;
-            }
-            if ( p != null && !t.getPredicate().equals( p ) )
-            {
-                continue;
-            }
-            if ( o != null && !t.getObject().equals( o ) )
-            {
-                continue;
-            }
-            return true;
-        }
-        return false ;
-    }
-}


[5/6] jena git commit: JENA-369: Output pretty lists in basic graph patterns.

Posted by an...@apache.org.
JENA-369: Output pretty lists in basic graph patterns.

This includes property functions.
Conversion is cautious - it looks for the triples as the parser
might output them.

Nested bnodes structures in lists are not converted back.


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

Branch: refs/heads/master
Commit: f19d8b267e1976f655e2c7509e6c7ce67c0c9496
Parents: 9a3a072
Author: Andy Seaborne <an...@apache.org>
Authored: Sat Jun 17 15:48:12 2017 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sun Jun 18 09:26:55 2017 +0100

----------------------------------------------------------------------
 .../jena/sparql/serializer/FmtEltLib.java       | 195 ++++++
 .../sparql/serializer/FormatterElement.java     | 688 ++++++++++---------
 .../sparql/serializer/TriplesListBlock.java     |  43 ++
 3 files changed, 612 insertions(+), 314 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/f19d8b26/jena-arq/src/main/java/org/apache/jena/sparql/serializer/FmtEltLib.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/serializer/FmtEltLib.java b/jena-arq/src/main/java/org/apache/jena/sparql/serializer/FmtEltLib.java
new file mode 100644
index 0000000..d14f3da
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/serializer/FmtEltLib.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.sparql.serializer;
+
+import static org.apache.jena.graph.Node.ANY;
+
+import java.util.*;
+
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.Triple;
+import org.apache.jena.sparql.core.BasicPattern;
+import org.apache.jena.vocabulary.RDF;
+
+/** Place to move some of the code from FormatterElement */ 
+class FmtEltLib {
+    
+    /*package*/ static Node rdfFirst = RDF.Nodes.first;
+    /*package*/ static Node rdfRest  = RDF.Nodes.rest;
+    /*package*/ static Node rdfNil   = RDF.Nodes.nil;
+
+    // Cautious list finder.  
+    //  The list must be like the parser creates them:
+    //   Adjacent triples, in first, rest order.
+
+    // It does support embedded lists.
+    // It does not support bnode structures i.e. [:prop :obj]
+    
+    // Ths code simply finds lists - it does not perform checks as to their suitablity to print in ()-form.
+    
+    /*package*/ static TriplesListBlock createTriplesListBlock(BasicPattern bgp) {
+        TriplesListBlock tlb = new TriplesListBlock();
+        List<Triple> triples = bgp.getList();
+        for ( int idx = 0 ; idx < triples.size() ; idx++ ) {
+            Triple t = triples.get(idx);
+            if ( idx == triples.size() - 1 )
+                // Can't be a following triple.
+                break;
+            // null -> ANY
+            if ( matches(t, ANY, rdfFirst, ANY) ) {
+                Node consCell = t.getSubject();
+                int numTriples = collectList(consCell, idx, triples, tlb);
+                if ( numTriples > 0 ) {
+                    // Skip triples.
+                    idx = idx + numTriples - 1 ;
+                } else {
+                    // Play safe
+                    // skip to (? rdf:rest rdf:nil) (if any).
+                    for ( idx = idx + 1 ; idx < triples.size() ; idx++ ) {
+                        Triple t2 = triples.get(idx);
+                        if ( matches(t2, ANY, rdfRest, rdfNil) ) 
+                            break;
+                    }
+                }
+            }
+        }
+        return tlb;
+    }
+    
+    private static Node nullAsAny(Node n) {
+        return n == null ? ANY : n ; 
+    }
+
+    /*package*/ static boolean matches(Triple t, Node s, Node p, Node o) {
+        s = nullAsAny(s) ;
+        p = nullAsAny(p) ;
+        o = nullAsAny(o) ;
+        if ( s != ANY && ! Objects.equals(s, t.getSubject()) )
+            return false ;
+        if ( p != ANY && ! Objects.equals(p, t.getPredicate()) )
+            return false ;
+        if ( o != ANY && ! Objects.equals(o, t.getObject()) )
+            return false ;
+        return true ;
+    }
+
+    /*package*/ static int collectList(Node consCell, int idx, List<Triple> triples, TriplesListBlock tlb) {
+        Set<Triple> listTriples = new LinkedHashSet<>();
+        TriplesListBlock block1 = collectList1(consCell, idx, triples, listTriples, tlb);
+        if ( block1 == null )
+            // Failed.
+            return -1;
+        if ( ! FormatterElement.FMT_FREE_STANDING_LISTS ) {
+            // Reject free standiang lists.
+            int inCount = count(triples, ANY, ANY, consCell);
+            int outCount = count(triples, consCell, ANY, ANY);
+            if ( inCount == 0 && outCount == 2 )
+                return -1;
+        }
+
+        int numTriples = block1.triplesInLists.size();
+        tlb.merge(block1);
+        return numTriples;
+    }
+
+    /**
+     * Spot parser pattern of adjacent "first-rest" pairs.
+     * Collect elements of a well-formed list else null.
+     * {@code triplesInList}.
+     */
+    /*package*/ static TriplesListBlock collectList1(Node consCell, int idx, List<Triple> triples, Set<Triple> triplesInList, TriplesListBlock tlb) {
+        // This list - accumulate separately because we aren't sure it is well-formed yet.
+        TriplesListBlock thisList = new TriplesListBlock();
+        List<Node> elts = new ArrayList<>();
+        thisList.listElementsMap.put(consCell, elts);
+        
+        for ( ;; ) {
+            if ( idx + 1 >= triples.size() )
+                // Last triple - can't be an rdf:first, rdf:rest pair.
+                return null;
+            Triple t1 = triples.get(idx);
+            consCell = t1.getSubject();
+            
+            Triple t2 = triples.get(idx + 1);
+            
+            // -- Checks on t1
+            // t1 : (consCell rdf:first element) 
+            if ( ! matches(t1, consCell, rdfFirst, ANY) )
+                return null;
+            
+            // ---- Possible compound value. 
+            // Second triple is rdf:rest, or rdf:first for a list in a list.
+            // or arbitrary triples for [:p :q] in a list.  
+            // We don't handle the latter case because programatic can make this anything.  
+
+            final boolean ListsInLists = true ;
+            if ( ListsInLists ) {
+                if ( rdfFirst.equals(t2.getPredicate()) && t1.getObject().equals(t2.getSubject()) ) {
+                    // Recursion.
+                    int numProcessed = collectList(t2.getSubject(), idx + 1, triples, thisList); // -1
+                    if ( numProcessed < 0 )
+                        return null;
+                    // Not "-1" - this loop does not have autoincrement.  
+                    idx = idx + numProcessed ;
+                    // idx: Posn of the rdf:nil. Probe to see if t2 is an "rdf:rest" to consider.
+                    t2 = triples.get(idx + 1);
+                }
+            }
+            
+            // -- Checks on t2
+            // t2 : (consCell rdf:rest element)
+            if ( ! matches(t2, consCell, rdfRest, ANY) )
+                return null;
+            // -- Check consCell - no other triples or one if a subject list.
+            int outCount = count(triples, consCell, ANY, ANY) ;
+            if ( outCount != 2 ) {
+                // Head cell also be a subject list. in which case the first cell of the list can have a count of 3. 
+                if ( outCount == 3 && ! elts.isEmpty() ) 
+                    return null;
+            }
+                
+            
+            int inCount = count(triples, ANY, ANY, consCell) ;
+            if ( inCount != 1 ) {
+                // Head cell can also be zero : subject or free standing list head.
+                if ( outCount == 0 && ! elts.isEmpty() ) 
+                    return null;
+            }
+                
+            
+            Node elt = t1.getObject();
+            thisList.triplesInLists.add(t1);
+            thisList.triplesInLists.add(t2);
+            elts.add(elt);
+            if ( matches(t2, ANY, ANY, rdfNil) ) {
+                return thisList;
+            }
+            idx += 2;
+        }
+    }
+    
+    /*package*/ static int count(List<Triple> triples, Node s, Node p, Node o) {
+        int count = 0 ;
+        for ( Triple t : triples ) {
+            if ( matches(t, s, p, o) )
+                count++;
+        }
+        return count;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/f19d8b26/jena-arq/src/main/java/org/apache/jena/sparql/serializer/FormatterElement.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/serializer/FormatterElement.java b/jena-arq/src/main/java/org/apache/jena/sparql/serializer/FormatterElement.java
index 2d1f6cc..4770fce 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/serializer/FormatterElement.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/serializer/FormatterElement.java
@@ -1,5 +1,5 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one
+f * 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
@@ -18,283 +18,286 @@
 
 package org.apache.jena.sparql.serializer;
 
-import java.util.ArrayList ;
-import java.util.Iterator ;
-import java.util.List ;
+import static org.apache.jena.graph.Node.ANY;
+import static org.apache.jena.sparql.serializer.FmtEltLib.count;
+import static org.apache.jena.sparql.serializer.FmtEltLib.createTriplesListBlock;
+import static org.apache.jena.sparql.serializer.FmtEltLib.rdfFirst;
 
-import org.apache.jena.atlas.io.IndentedLineBuffer ;
-import org.apache.jena.atlas.io.IndentedWriter ;
-import org.apache.jena.graph.Node ;
-import org.apache.jena.graph.Triple ;
-import org.apache.jena.query.Query ;
+import java.util.*;
+
+import org.apache.jena.atlas.io.IndentedLineBuffer;
+import org.apache.jena.atlas.io.IndentedWriter;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.Triple;
+import org.apache.jena.query.Query;
 import org.apache.jena.query.QueryVisitor;
 import org.apache.jena.query.Syntax;
-import org.apache.jena.sparql.core.BasicPattern ;
-import org.apache.jena.sparql.core.PathBlock ;
-import org.apache.jena.sparql.core.TriplePath ;
-import org.apache.jena.sparql.expr.Expr ;
-import org.apache.jena.sparql.path.PathWriter ;
-import org.apache.jena.sparql.syntax.* ;
-import org.apache.jena.sparql.util.FmtUtils ;
-import org.apache.jena.vocabulary.RDF ;
-
-
-public class FormatterElement extends FormatterBase
-    implements ElementVisitor
-{
-    public static final int INDENT = 2 ; 
-    
+import org.apache.jena.sparql.core.BasicPattern;
+import org.apache.jena.sparql.core.PathBlock;
+import org.apache.jena.sparql.core.TriplePath;
+import org.apache.jena.sparql.expr.Expr;
+import org.apache.jena.sparql.path.PathWriter;
+import org.apache.jena.sparql.syntax.*;
+import org.apache.jena.sparql.util.FmtUtils;
+import org.apache.jena.vocabulary.RDF;
+
+public class FormatterElement extends FormatterBase implements ElementVisitor {
+    public static final int     INDENT                   = 2;
+
     /** Control whether to show triple pattern boundaries - creates extra nesting */
-    public static final boolean PATTERN_MARKERS = false ;
-    
-//    /** Control whether triple patterns always have a final dot - it can be dropped in some cases */
-//    public static boolean PATTERN_FINAL_DOT = false ;
+    public static final boolean PATTERN_MARKERS          = false;
+
+// /** Control whether triple patterns always have a final dot - it can be dropped in some cases */
+// public static boolean PATTERN_FINAL_DOT = false ;
 
     /** Control whether (non-triple) patterns have a final dot - it can be dropped */
-    public static final boolean GROUP_SEP_DOT = false ;
-    
+    public static final boolean GROUP_SEP_DOT            = false;
+
     /** Control whether the first item of a group is on the same line as the { */
-    public static final boolean GROUP_FIRST_ON_SAME_LINE = true ;
+    public static final boolean GROUP_FIRST_ON_SAME_LINE = true;
 
     /** Control pretty printing */
-    public static final boolean PRETTY_PRINT = true  ;
+    public static final boolean PRETTY_PRINT             = true;
 
-    /** Control whether disjunction has set of delimiters - as it's a group usually, these aren't needed */
-    public static final boolean UNION_MARKERS = false ;
+    /** Control pretty printing of RDF lists */
+    public static final boolean FMT_LISTS                = true;
     
+    /** Control pretty printing of free standing RDF lists */
+    // Do *not* set "true" - argument of property paths can be lists and these spane
+    // PathBlocks and Basic Graph Patterns and this is not handled prop.
+    public static final boolean FMT_FREE_STANDING_LISTS  = false;
+
+    /**
+     * Control whether disjunction has set of delimiters - as it's a group usually, these
+     * aren't needed
+     */
+    public static final boolean UNION_MARKERS            = false;
+
     /** Control whether GRAPH indents in a fixed way or based on the layout size */
-    public static final boolean GRAPH_FIXED_INDENT = true ;
-    
-    /** Control whether NOT EXIST/EXISTS indents in a fixed way or based on the layout size */
-    public static final boolean ELEMENT1_FIXED_INDENT = true ;
-    
+    public static final boolean GRAPH_FIXED_INDENT       = true;
+
+    /**
+     * Control whether NOT EXIST/EXISTS indents in a fixed way or based on the layout size
+     */
+    public static final boolean ELEMENT1_FIXED_INDENT    = true;
+
     /** Control triples pretty printing */
-    public static final int TRIPLES_SUBJECT_COLUMN = 8 ;
-    
+    public static final int     TRIPLES_SUBJECT_COLUMN   = 8;
+
     // Less than this => rest of triple on the same line
-    // Could be smart and make it depend on the property length as well.  Later.
-    public static final int TRIPLES_SUBJECT_LONG = 12 ;     
+    // Could be smart and make it depend on the property length as well. Later.
+    public static final int     TRIPLES_SUBJECT_LONG     = 12;
 
-    public static final int TRIPLES_PROPERTY_COLUMN = 20;
-    
-    public static final int TRIPLES_COLUMN_GAP = 2 ;
+    public static final int     TRIPLES_PROPERTY_COLUMN  = 20;
+
+    public static final int     TRIPLES_COLUMN_GAP       = 2;
 
     public FormatterElement(IndentedWriter out, SerializationContext context) {
-        super(out, context) ;
+        super(out, context);
     }
 
     public static void format(IndentedWriter out, SerializationContext cxt, Element el) {
-        FormatterElement fmt = new FormatterElement(out, cxt) ;
-        fmt.startVisit() ;
-        el.visit(fmt) ;
-        fmt.finishVisit() ;
+        FormatterElement fmt = new FormatterElement(out, cxt);
+        fmt.startVisit();
+        el.visit(fmt);
+        fmt.finishVisit();
     }
 
     public static String asString(Element el) {
-        SerializationContext cxt = new SerializationContext() ;
-        IndentedLineBuffer b = new IndentedLineBuffer() ;
-        FormatterElement.format(b, cxt, el) ;
-        return b.toString() ;
+        SerializationContext cxt = new SerializationContext();
+        IndentedLineBuffer b = new IndentedLineBuffer();
+        FormatterElement.format(b, cxt, el);
+        return b.toString();
     }
 
     public boolean topMustBeGroup() {
-        return false ;
+        return false;
     }
 
     @Override
     public void visit(ElementTriplesBlock el) {
         if ( el.isEmpty() ) {
-            out.println("# Empty BGP") ;
-            return ;
+            out.println("# Empty BGP");
+            return;
         }
-        formatTriples(el.getPattern()) ;
+        formatTriples(el.getPattern());
     }
 
     @Override
     public void visit(ElementPathBlock el) {
-        // Write path block - don't put in a final trailing "." 
+        // Write path block - don't put in a final trailing "."
         if ( el.isEmpty() ) {
-            out.println("# Empty BGP") ;
-            return ;
+            out.println("# Empty BGP");
+            return;
         }
 
         // Split into BGP-path-BGP-...
         // where the BGPs may be empty.
-        PathBlock pBlk = el.getPattern() ;
-        BasicPattern bgp = new BasicPattern() ;
-        boolean first = true ;      // Has anything been output?
+        PathBlock pBlk = el.getPattern();
+        BasicPattern bgp = new BasicPattern();
+        boolean first = true;      // Has anything been output?
         for ( TriplePath tp : pBlk ) {
             if ( tp.isTriple() ) {
-                bgp.add(tp.asTriple()) ;
-                continue ;
+                bgp.add(tp.asTriple());
+                continue;
             }
-            
+
             if ( !bgp.isEmpty() ) {
                 if ( !first )
-                    out.println(" .") ;
-                flush(bgp) ;
-                first = false ;
+                    out.println(" .");
+                flush(bgp);
+                first = false;
             }
             if ( !first )
-                out.println(" .") ;
-            // Path
-            printSubject(tp.getSubject()) ;
-            out.print(" ") ;
-            PathWriter.write(out, tp.getPath(), context.getPrologue()) ;
-            out.print(" ") ;
-            printObject(tp.getObject()) ;
-            first = false ;
+                out.println(" .");
+            // Path (no RDF list output).
+            printSubject(tp.getSubject());
+            out.print(" ");
+            PathWriter.write(out, tp.getPath(), context.getPrologue());
+            out.print(" ");
+            printObject(tp.getObject());
+            first = false;
         }
         // Flush any stored triple patterns.
         if ( !bgp.isEmpty() ) {
             if ( !first )
-                out.println(" .") ;
-            flush(bgp) ;
-            first = false ;
+                out.println(" .");
+            flush(bgp);
+            first = false;
         }
     }
 
-    private void flush(BasicPattern bgp) {
-        formatTriples(bgp) ;
-        bgp.getList().clear(); 
-    }
-
     @Override
-    public void visit(ElementDataset el)
-    {
-//        if ( el.getDataset() != null)
-//        {
-//            DatasetGraph dsNamed = el.getDataset() ;
-//            out.print("DATASET ") ;
-//            out.incIndent(INDENT) ;
-//            Iterator iter = dsNamed.listNames() ;
-//            if ( iter.hasNext() )
-//            {
-//                boolean first = false ;
-//                for ( ; iter.hasNext() ; )
-//                {
-//                    if ( ! first )
-//                        out.newline() ;
-//                    out.print("FROM <") ;
-//                    String s = (String)iter.next() ; 
-//                    out.print(s) ;
-//                    out.print(">") ;
+    public void visit(ElementDataset el) {
+        // Not implemented.
+//        if ( el.getDataset() != null ) {
+//            DatasetGraph dsNamed = el.getDataset();
+//            out.print("DATASET ");
+//            out.incIndent(INDENT);
+//            Iterator<Node> iter = dsNamed.listGraphNodes();
+//            if ( iter.hasNext() ) {
+//                boolean first = false;
+//                for ( ; iter.hasNext() ; ) {
+//                    if ( !first )
+//                        out.newline();
+//                    out.print("FROM <");
+//                    Node n = iter.next();
+//                    out.print(slotToString(n));
+//                    out.print(">");
 //                }
 //            }
-//            out.decIndent(INDENT) ;
-//            out.newline() ;
+//            out.decIndent(INDENT);
+//            out.newline();
 //        }
-        if ( el.getElement() != null )
-            visitAsGroup(el.getElement()) ;
+//        if ( el.getElement() != null )
+//            visitAsGroup(el.getElement());
     }
 
     @Override
     public void visit(ElementFilter el) {
-        out.print("FILTER ") ;
-        Expr expr = el.getExpr() ;
-        FmtExprSPARQL v = new FmtExprSPARQL(out, context) ;
+        out.print("FILTER ");
+        Expr expr = el.getExpr();
+        FmtExprSPARQL v = new FmtExprSPARQL(out, context);
 
         // This assumes that complex expressions are bracketted
         // (parens) as necessary except for some cases:
         // Plain variable or constant
 
-        boolean addParens = false ;
+        boolean addParens = false;
         if ( expr.isVariable() )
-            addParens = true ;
+            addParens = true;
         if ( expr.isConstant() )
-            addParens = true ;
+            addParens = true;
 
         if ( addParens )
-            out.print("( ") ;
-        v.format(expr) ;
+            out.print("( ");
+        v.format(expr);
         if ( addParens )
-            out.print(" )") ;
+            out.print(" )");
     }
 
     @Override
     public void visit(ElementAssign el) {
-        out.print("LET (") ;
-        out.print("?" + el.getVar().getVarName()) ;
-        out.print(" := ") ;
-        FmtExprSPARQL v = new FmtExprSPARQL(out, context) ;
-        v.format(el.getExpr()) ;
-        out.print(")") ;
+        out.print("LET (");
+        out.print("?" + el.getVar().getVarName());
+        out.print(" := ");
+        FmtExprSPARQL v = new FmtExprSPARQL(out, context);
+        v.format(el.getExpr());
+        out.print(")");
     }
 
     @Override
     public void visit(ElementBind el) {
-        out.print("BIND(") ;
-        FmtExprSPARQL v = new FmtExprSPARQL(out, context) ;
-        v.format(el.getExpr()) ;
-        out.print(" AS ") ;
-        out.print("?" + el.getVar().getVarName()) ;
-        out.print(")") ;
+        out.print("BIND(");
+        FmtExprSPARQL v = new FmtExprSPARQL(out, context);
+        v.format(el.getExpr());
+        out.print(" AS ");
+        out.print("?" + el.getVar().getVarName());
+        out.print(")");
     }
 
     @Override
     public void visit(ElementData el) {
-        QuerySerializer.outputDataBlock(out, el.getVars(), el.getRows(), context) ;
+        QuerySerializer.outputDataBlock(out, el.getVars(), el.getRows(), context);
     }
 
     @Override
     public void visit(ElementUnion el) {
         if ( el.getElements().size() == 1 ) {
             // If this is an element of just one, just do it inplace
-            // Can't happen from a parsed query.
-            // Now can :-)
-
-            // SPARQL 1.1 inline UNION.
-            // Same as OPTIONAL, MINUS
-            out.print("UNION") ;
-            out.incIndent(INDENT) ;
-            out.newline() ;
-            visitAsGroup(el.getElements().get(0)) ;
-            out.decIndent(INDENT) ;
-            return ;
+            // Can't happen from a parsed query in SPARQL.
+            visitAsGroup(el.getElements().get(0));
+//            // Same as OPTIONAL, MINUS
+//            out.print("UNION");
+//            out.incIndent(INDENT);
+//            out.newline();
+//            visitAsGroup(el.getElements().get(0));
+//            out.decIndent(INDENT);
+            return;
         }
 
         if ( UNION_MARKERS ) {
-            out.print("{") ;
-            out.newline() ;
-            out.pad() ;
+            out.print("{");
+            out.newline();
+            out.pad();
         }
 
-        out.incIndent(INDENT) ;
+        out.incIndent(INDENT);
 
-        boolean first = true ;
+        boolean first = true;
         for ( Element subElement : el.getElements() ) {
             if ( !first ) {
-                out.decIndent(INDENT) ;
-                out.newline() ;
-                out.print("UNION") ;
-                out.newline() ;
-                out.incIndent(INDENT) ;
+                out.decIndent(INDENT);
+                out.newline();
+                out.print("UNION");
+                out.newline();
+                out.incIndent(INDENT);
             }
-            visitAsGroup(subElement) ;
-            first = false ;
+            visitAsGroup(subElement);
+            first = false;
         }
 
-        out.decIndent(INDENT) ;
+        out.decIndent(INDENT);
 
         if ( UNION_MARKERS ) {
-            out.newline() ;
-            out.print("}") ;
+            out.newline();
+            out.print("}");
         }
     }
 
     @Override
     public void visit(ElementGroup el) {
-        out.print("{") ;
-        int initialRowNumber = out.getRow() ;
-        out.incIndent(INDENT) ;
+        out.print("{");
+        int initialRowNumber = out.getRow();
+        out.incIndent(INDENT);
         if ( !GROUP_FIRST_ON_SAME_LINE )
-            out.newline() ;
+            out.newline();
 
-        int row1 = out.getRow() ;
-        out.pad() ;
+        int row1 = out.getRow();
+        out.pad();
 
-        boolean first = true ;
-        Element lastElt = null ;
+        boolean first = true;
+        Element lastElt = null;
 
         for ( Element subElement : el.getElements() ) {
             // Some adjacent elements need a DOT:
@@ -303,302 +306,359 @@ public class FormatterElement extends FormatterBase
                 // Need to move on after the last thing printed.
                 // Check for necessary DOT as separator
                 if ( GROUP_SEP_DOT || needsDotSeparator(lastElt, subElement) )
-                    out.print(" . ") ;
-                out.newline() ;
+                    out.print(" . ");
+                out.newline();
             }
-            subElement.visit(this) ;
-            first = false ;
-            lastElt = subElement ;
+            subElement.visit(this);
+            first = false;
+            lastElt = subElement;
         }
-        out.decIndent(INDENT) ;
+        out.decIndent(INDENT);
 
         // Where to put the closing "}"
-        int row2 = out.getRow() ;
+        int row2 = out.getRow();
         if ( row1 != row2 )
-            out.newline() ;
+            out.newline();
 
         // Finally, close the group.
         if ( out.getRow() == initialRowNumber )
-            out.print(" ") ;
-        out.print("}") ;
+            out.print(" ");
+        out.print("}");
     }
 
     private static boolean needsDotSeparator(Element el1, Element el2) {
-        return needsDotSeparator(el1) && needsDotSeparator(el2) ;
+        return needsDotSeparator(el1) && needsDotSeparator(el2);
     }
 
     private static boolean needsDotSeparator(Element el) {
-        return (el instanceof ElementTriplesBlock) || (el instanceof ElementPathBlock) ;
+        return (el instanceof ElementTriplesBlock) || (el instanceof ElementPathBlock);
     }
 
     @Override
     public void visit(ElementOptional el) {
-        out.print("OPTIONAL") ;
-        out.incIndent(INDENT) ;
-        out.newline() ;
-        visitAsGroup(el.getOptionalElement()) ;
-        out.decIndent(INDENT) ;
+        out.print("OPTIONAL");
+        out.incIndent(INDENT);
+        out.newline();
+        visitAsGroup(el.getOptionalElement());
+        out.decIndent(INDENT);
     }
 
     @Override
     public void visit(ElementNamedGraph el) {
-        visitNodePattern("GRAPH", el.getGraphNameNode(), el.getElement()) ;
+        visitNodePattern("GRAPH", el.getGraphNameNode(), el.getElement());
     }
 
     @Override
     public void visit(ElementService el) {
-        String x = "SERVICE" ;
+        String x = "SERVICE";
         if ( el.getSilent() )
-            x = "SERVICE SILENT" ;
-        visitNodePattern(x, el.getServiceNode(), el.getElement()) ;
+            x = "SERVICE SILENT";
+        visitNodePattern(x, el.getServiceNode(), el.getElement());
     }
 
     private void visitNodePattern(String label, Node node, Element subElement) {
-        int len = label.length() ;
-        out.print(label) ;
-        out.print(" ") ;
-        String nodeStr = (node == null) ? "*" : slotToString(node) ;
-        out.print(nodeStr) ;
-        len += nodeStr.length() ;
+        int len = label.length();
+        out.print(label);
+        out.print(" ");
+        String nodeStr = (node == null) ? "*" : slotToString(node);
+        out.print(nodeStr);
+        len += nodeStr.length();
         if ( GRAPH_FIXED_INDENT ) {
-            out.incIndent(INDENT) ;
-            out.newline() ; // NB and newline
+            out.incIndent(INDENT);
+            out.newline(); // NB and newline
         } else {
-            out.print(" ") ;
-            len++ ;
-            out.incIndent(len) ;
+            out.print(" ");
+            len++;
+            out.incIndent(len);
         }
-        visitAsGroup(subElement) ;
+        visitAsGroup(subElement);
 
         if ( GRAPH_FIXED_INDENT )
-            out.decIndent(INDENT) ;
+            out.decIndent(INDENT);
         else
-            out.decIndent(len) ;
+            out.decIndent(len);
     }
 
     private void visitElement1(String label, Element1 el) {
 
-        int len = label.length() ;
-        out.print(label) ;
-        len += label.length() ;
+        int len = label.length();
+        out.print(label);
+        len += label.length();
         if ( ELEMENT1_FIXED_INDENT ) {
-            out.incIndent(INDENT) ;
-            out.newline() ; // NB and newline
+            out.incIndent(INDENT);
+            out.newline(); // NB and newline
         } else {
-            out.print(" ") ;
-            len++ ;
-            out.incIndent(len) ;
+            out.print(" ");
+            len++;
+            out.incIndent(len);
         }
-        visitAsGroup(el.getElement()) ;
+        visitAsGroup(el.getElement());
         if ( ELEMENT1_FIXED_INDENT )
-            out.decIndent(INDENT) ;
+            out.decIndent(INDENT);
         else
-            out.decIndent(len) ;
+            out.decIndent(len);
     }
 
     @Override
     public void visit(ElementExists el) {
-        visitElement1("EXISTS", el) ;
+        visitElement1("EXISTS", el);
     }
 
     @Override
     public void visit(ElementNotExists el) {
-        visitElement1("NOT EXISTS", el) ;
+        visitElement1("NOT EXISTS", el);
     }
 
     @Override
     public void visit(ElementMinus el) {
-        out.print("MINUS") ;
-        out.incIndent(INDENT) ;
-        out.newline() ;
-        visitAsGroup(el.getMinusElement()) ;
-        out.decIndent(INDENT) ;
+        out.print("MINUS");
+        out.incIndent(INDENT);
+        out.newline();
+        visitAsGroup(el.getMinusElement());
+        out.decIndent(INDENT);
     }
 
     @Override
     public void visit(ElementSubQuery el) {
-        out.print("{ ") ;
-        out.incIndent(INDENT) ;
-        Query q = el.getQuery() ;
+        out.print("{ ");
+        out.incIndent(INDENT);
+        Query q = el.getQuery();
 
         // Serialize with respect to the existing context
-        QuerySerializerFactory factory = SerializerRegistry.get().getQuerySerializerFactory(Syntax.syntaxARQ) ;
-        QueryVisitor serializer = factory.create(Syntax.syntaxARQ, context, out) ;
-        q.visit(serializer) ;
+        QuerySerializerFactory factory = SerializerRegistry.get().getQuerySerializerFactory(Syntax.syntaxARQ);
+        QueryVisitor serializer = factory.create(Syntax.syntaxARQ, context, out);
+        q.visit(serializer);
 
-        out.decIndent(INDENT) ;
-        out.print("}") ;
+        out.decIndent(INDENT);
+        out.print("}");
     }
 
     public void visitAsGroup(Element el) {
-        boolean needBraces = !((el instanceof ElementGroup) || (el instanceof ElementSubQuery)) ;
+        boolean needBraces = !((el instanceof ElementGroup) || (el instanceof ElementSubQuery));
 
         if ( needBraces ) {
-            out.print("{ ") ;
-            out.incIndent(INDENT) ;
+            out.print("{ ");
+            out.incIndent(INDENT);
         }
 
-        el.visit(this) ;
+        el.visit(this);
 
         if ( needBraces ) {
-            out.decIndent(INDENT) ;
-            out.print("}") ;
+            out.decIndent(INDENT);
+            out.print("}");
         }
     }
-
-    int subjectWidth = -1 ;
-    int predicateWidth = -1 ;
     
+    // -------- Formatting a basic graph pattern
+    // Triple order is preserved.
+
+    int subjectWidth   = -1;
+    int predicateWidth = -1;
+
     @Override
     protected void formatTriples(BasicPattern triples) {
         if ( !PRETTY_PRINT ) {
-            super.formatTriples(triples) ;
-            return ;
+            super.formatTriples(triples);
+            return;
         }
 
-        // TODO RDF Collections - spot the parsers pattern
         if ( triples.isEmpty() )
-            return ;
+            return;
+
+        // Lists in this BasicPattern.
+        // TriplesListBlock is a record of lists in this BGP.
+        // Formatting is off for list if there is an empty TriplesListBlock.
+        // This is cautionsly spotting the triples from RDF lists as generated by the
+        // parser.
 
-        setWidths(triples) ;
+        TriplesListBlock block = FMT_LISTS 
+            ? createTriplesListBlock(triples) 
+            : new TriplesListBlock();
+        
+        Set<Node> freeStanding = new HashSet<>();
+        for ( Node head : block.listElementsMap.keySet() ) {
+            // Check for suitablity to print.
+            // See also FmtEltLib#collectList
+            //
+            // Subject-list : inCount = 0, outCount = 3
+            // Object-list :  inCount = 1, outCount = 2
+            // Free-standing list :  inCount = 0, outCount = 2
+            //     Free-standing list is handled as a special case. 
+            int inCount = count(triples.getList(), ANY, ANY, head);
+            int outCount = count(triples.getList(), head, ANY, ANY);
+            if ( inCount == 0 && outCount == 2 )
+                // Free standing.
+                freeStanding.add(head);
+        }
+
+        setWidths(triples);
         if ( subjectWidth > TRIPLES_SUBJECT_COLUMN )
-            subjectWidth = TRIPLES_SUBJECT_COLUMN ;
+            subjectWidth = TRIPLES_SUBJECT_COLUMN;
         if ( predicateWidth > TRIPLES_PROPERTY_COLUMN )
-            predicateWidth = TRIPLES_PROPERTY_COLUMN ;
+            predicateWidth = TRIPLES_PROPERTY_COLUMN;
 
-        // Loops:
-        List<Triple> subjAcc = new ArrayList<>() ; // Accumulate all triples
-                                                   // with the same subject.
-        Node subj = null ; // Subject being accumulated
+        // Accumulate all triples with the same subject.
+        List<Triple> subjAcc = new ArrayList<>();
+        // Subject being accumulated
+        Node subj = null;
+        // Print newlines between blocks.
+        boolean first = true;
 
-        boolean first = true ; // Print newlines between blocks.
-
-        int indent = -1 ;
+        int indent = -1;
         for ( Triple t : triples ) {
+            if ( block.triplesInLists.contains(t) ) {
+                if ( rdfFirst.equals(t.getPredicate()) ) {
+                    if ( freeStanding.contains(t.getSubject()) )
+                        printNodeOrList(t.getSubject(), block.listElementsMap);
+                }
+                continue;
+            }
+
             if ( subj != null && t.getSubject().equals(subj) ) {
-                subjAcc.add(t) ;
-                continue ;
+                subjAcc.add(t);
+                continue;
             }
 
             if ( subj != null ) {
                 if ( !first )
-                    out.println(" .") ;
-                formatSameSubject(subj, subjAcc) ;
-                first = false ;
+                    out.println(" .");
+                formatSameSubject(subj, subjAcc, block.listElementsMap);
+                first = false;
                 // At end of line of a block of triples with same subject.
                 // Drop through and start new block of same subject triples.
             }
 
             // New subject
-            subj = t.getSubject() ;
-            subjAcc.clear() ;
-            subjAcc.add(t) ;
+            subj = t.getSubject();
+            subjAcc.clear();
+            subjAcc.add(t);
         }
 
         // Flush accumulator
         if ( subj != null && subjAcc.size() != 0 ) {
             if ( !first )
-                out.println(" .") ;
-            first = false ;
-            formatSameSubject(subj, subjAcc) ;
+                out.println(" .");
+            first = false;
+            formatSameSubject(subj, subjAcc, block.listElementsMap);
         }
     }
 
-    private void formatSameSubject(Node subject, List<Triple> triples) {
+    // ----
+
+    private void flush(BasicPattern bgp) {
+        formatTriples(bgp);
+        bgp.getList().clear();
+    }
+
+    private void formatSameSubject(Node subject, List<Triple> triples, Map<Node, List<Node>> lists) {
+
         if ( triples == null || triples.size() == 0 )
-            return ;
-        
-        // Do the first triple.
-        Iterator<Triple> iter = triples.iterator() ;
-        Triple t1 = iter.next() ; 
+            return;
 
-//        int indent = TRIPLES_SUBJECT_COLUMN+TRIPLES_COLUMN_GAP ;
-//        // Long subject => same line.  Works for single triple as well.
-//        int s1_len = printSubject(t1.getSubject()) ;
-//        //int x = out.getCol() ;
+        // Do the first triple.
+        Iterator<Triple> iter = triples.iterator();
+        Triple t1 = iter.next();
 
-        int indent = subjectWidth + TRIPLES_COLUMN_GAP ;
-        int s1_len = printSubject(t1.getSubject()) ;
+        int indent = subjectWidth + TRIPLES_COLUMN_GAP;
 
+        int s1_len = printNodeOrList(subject, lists);
         if ( s1_len > TRIPLES_SUBJECT_LONG ) {
-            // Too long - start a new line.
-            out.incIndent(indent) ;
-            out.println() ;
+            out.incIndent(indent);
+            out.println();
         } else {
-            printGap() ;
-            out.incIndent(indent) ;
+            printGap();
+            out.incIndent(indent);
         }
 
         // Remainder of first triple
-        printProperty(t1.getPredicate()) ;
-        printGap() ;
-        printObject(t1.getObject()) ;
+        printProperty(t1.getPredicate());
+        printGap();
 
-        // Do the rest
+        printNodeOrList(t1.getObject(), lists);
 
+        // Do the rest
         for ( ; iter.hasNext() ; ) {
-            Triple t = iter.next() ;
-            out.println(" ;") ;
-            printProperty(t.getPredicate()) ;
-            printGap() ;
-            printObject(t.getObject()) ;
-            continue ;
-            // print property list
+            Triple t = iter.next();
+            out.println(" ;");
+            printProperty(t.getPredicate());
+            printGap();
+            printNodeOrList(t.getObject(), lists);
+            continue;
         }
 
         // Finish off the block.
-        out.decIndent(indent) ;
+        out.decIndent(indent);
         // out.print(" .") ;
     }
 
+    private int printNodeOrList(Node node, Map<Node, List<Node>> lists) {
+        if ( lists.containsKey(node) )
+            return printList(lists.get(node), lists);
+        else
+            return printNoCol(node);
+    }
+
     private void setWidths(BasicPattern triples) {
-        subjectWidth = -1 ;
-        predicateWidth = -1 ;
+        subjectWidth = -1;
+        predicateWidth = -1;
 
         for ( Triple t : triples ) {
-            String s = slotToString(t.getSubject()) ;
+            String s = slotToString(t.getSubject());
             if ( s.length() > subjectWidth )
-                subjectWidth = s.length() ;
+                subjectWidth = s.length();
 
-            String p = slotToString(t.getPredicate()) ;
+            String p = slotToString(t.getPredicate());
             if ( p.length() > predicateWidth )
-                predicateWidth = p.length() ;
+                predicateWidth = p.length();
         }
     }
 
     private void printGap() {
-        out.print(' ', TRIPLES_COLUMN_GAP) ;
+        out.print(' ', TRIPLES_COLUMN_GAP);
     }
 
-    // Indent must be set first.
+    // printSubject, printObject - used in ElementPathBlock.
     private int printSubject(Node s) {
-        String str = slotToString(s) ;
-        out.print(str) ;
-        out.pad(subjectWidth) ;
-        return str.length() ;
+        return printNoCol(s);
     }
 
     // Assumes the indent is TRIPLES_SUBJECT_COLUMN+GAP
-    private static String RDFTYPE = FmtUtils.stringForNode(RDF.Nodes.type, new SerializationContext()) ;
-    
+    private static String RDFTYPE = FmtUtils.stringForNode(RDF.Nodes.type, new SerializationContext());
+
     private int printProperty(Node p) {
-        String str = slotToString(p) ;
+        String str = slotToString(p);
         if ( p.equals(RDF.Nodes.type) && str.equals(RDFTYPE) )
-            out.print("a") ;
+            out.print("a");
         else
-            out.print(str) ;
-        out.pad(predicateWidth) ;
-        return str.length() ;
+            out.print(str);
+        out.pad(predicateWidth);
+        return str.length();
     }
 
     private int printObject(Node obj) {
-        return printNoCol(obj) ;
+        return printNoCol(obj);
     }
 
-    private int printNoCol(Node node) {
-        String str = slotToString(node) ;
-        out.print(str) ;
-        return str.length() ;
+    private int printList(List<Node> list, Map<Node, List<Node>> lists) {
+        if ( list.isEmpty() ) {
+            out.print("()");
+            return 2;
+        }
+            
+        int col0 = out.getCol();
+        out.print("( ");
+        for ( Node n : list ) {
+            printNodeOrList(n, lists);
+            out.print(" ");
+        }
+        out.print(")");
+        int col1 = out.getCol();
+        return col1 - col0;
+    }
 
+    private int printNoCol(Node node) {
+        String str = slotToString(node);
+        out.print(str);
+        return str.length();
     }
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/f19d8b26/jena-arq/src/main/java/org/apache/jena/sparql/serializer/TriplesListBlock.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/serializer/TriplesListBlock.java b/jena-arq/src/main/java/org/apache/jena/sparql/serializer/TriplesListBlock.java
new file mode 100644
index 0000000..37671b8
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/serializer/TriplesListBlock.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.sparql.serializer;
+
+import java.util.*;
+
+import org.apache.jena.atlas.iterator.Iter;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.Triple;
+
+/** Internal record of list details. */
+/*package*/ class TriplesListBlock {
+    Map<Node, List<Node>> listElementsMap = new HashMap<>();
+    // Triples in lists.
+    Set<Triple>           triplesInLists  = new LinkedHashSet<>();
+
+    /*package*/ void merge(TriplesListBlock other) {
+        listElementsMap.putAll(other.listElementsMap);
+        triplesInLists.addAll(other.triplesInLists);
+    }
+        
+    @Override
+    public String toString() {
+        return Iter.asString(listElementsMap.keySet(), ", ") + "\n" + "{"+ Iter.asString(triplesInLists.iterator(), "\n")+"}";
+            
+    }
+}
\ No newline at end of file


[2/6] jena git commit: JENA-1361: Convert back to blank nodes.

Posted by an...@apache.org.
JENA-1361: Convert back to blank nodes.

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

Branch: refs/heads/master
Commit: d377dd141028ae81ed373b86d3fc8f26cc898447
Parents: bb7af3b
Author: Andy Seaborne <an...@apache.org>
Authored: Sat Jun 17 15:44:48 2017 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Sat Jun 17 15:44:48 2017 +0100

----------------------------------------------------------------------
 .../apache/jena/sparql/modify/request/UpdateWriter.java   |  2 ++
 .../jena/sparql/modify/request/UpdateWriterVisitor.java   | 10 ++++++----
 2 files changed, 8 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/d377dd14/jena-arq/src/main/java/org/apache/jena/sparql/modify/request/UpdateWriter.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/modify/request/UpdateWriter.java b/jena-arq/src/main/java/org/apache/jena/sparql/modify/request/UpdateWriter.java
index c2a2e35..1f79f55 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/modify/request/UpdateWriter.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/modify/request/UpdateWriter.java
@@ -54,6 +54,8 @@ public class UpdateWriter implements UpdateSerializer
         // To get legal syntax out, the serialization context 
         // has to be a bNode mapping that does ??N vars to bNodes
         if (sCxt == null)
+            // This is the one used for INSERT and DELETE templates.
+            // For the WHERE clause, see UpdateWriterVisitor.prepareElementFormatter
             sCxt = new SerializationContext((Prologue)null, new NodeToLabelMapBNode());
         
         this.out = out;

http://git-wip-us.apache.org/repos/asf/jena/blob/d377dd14/jena-arq/src/main/java/org/apache/jena/sparql/modify/request/UpdateWriterVisitor.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/modify/request/UpdateWriterVisitor.java b/jena-arq/src/main/java/org/apache/jena/sparql/modify/request/UpdateWriterVisitor.java
index e8a19ec..7672f71 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/modify/request/UpdateWriterVisitor.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/modify/request/UpdateWriterVisitor.java
@@ -32,6 +32,7 @@ import org.apache.jena.sparql.serializer.FormatterElement ;
 import org.apache.jena.sparql.serializer.SerializationContext ;
 import org.apache.jena.sparql.syntax.Element ;
 import org.apache.jena.sparql.util.FmtUtils ;
+import org.apache.jena.sparql.util.NodeToLabelMapBNode ;
 
 public class UpdateWriterVisitor implements UpdateVisitor
 {
@@ -212,7 +213,6 @@ public class UpdateWriterVisitor implements UpdateVisitor
         String $ = FmtUtils.stringForNode(node, sCxt) ;
         out.print($) ;
     }
-
     
     @Override
     public void visit(UpdateDeleteWhere update)
@@ -233,7 +233,6 @@ public class UpdateWriterVisitor implements UpdateVisitor
             output(update.getWithIRI()) ;
         }
         
-        
         if ( update.hasDeleteClause() )
         {
             List<Quad> deleteQuads = update.getDeleteQuads() ;
@@ -242,7 +241,6 @@ public class UpdateWriterVisitor implements UpdateVisitor
             outputQuadsBraced(deleteQuads) ;
         }
         
-        
         if ( update.hasInsertClause() )
         {
             List<Quad> insertQuads = update.getInsertQuads() ;
@@ -272,6 +270,7 @@ public class UpdateWriterVisitor implements UpdateVisitor
             output(x) ;
         }
          
+        // Wrong.
         Element el = update.getWherePattern() ;
         out.ensureStartOfLine() ;
         out.print("WHERE") ;
@@ -289,6 +288,9 @@ public class UpdateWriterVisitor implements UpdateVisitor
     }
 
     protected FormatterElement prepareElementFormatter() {
-        return new FormatterElement(out, sCxt);
+        SerializationContext sCxt1 = new  SerializationContext(sCxt);
+        // The label prefix is different to the template writer just for clarity.
+        sCxt1.setBNodeMap(new NodeToLabelMapBNode("x", false));
+        return new FormatterElement(out, sCxt1);
     }
 }
\ No newline at end of file