Merge pull request #635 from afs/thrift-update

JENA-1781: Update for Thrift 0.13.0, including workaround for THRIFT-5022
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 e55e13c..eb3861d 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
@@ -710,7 +710,6 @@
                     writePredicateObjectList(p, rdfSimpleNodes, predicateMaxWidth, first) ;
                     first = false ;
                 }
-
                 for ( Node o : rdfComplexNodes ) {
                     writePredicateObject(p, o, predicateMaxWidth, first) ;
                     first = false ;
@@ -752,9 +751,7 @@
 
         /** Write a predicate - jump to next line if deemed long */
         private void writePredicate(Node p, int predicateMaxWidth, boolean first) {
-            if ( first )
-                first = false ;
-            else {
+            if ( ! first ) {
                 print(" ;") ;
                 println() ;
             }
@@ -788,13 +785,22 @@
             return x ;
         }
 
-        private int countPredicates(Collection<Triple> cluster) {
-            Set<Node> x = new HashSet<>() ;
+        // Compact if one triple, or one predicate and several non-pretty objects.
+        private boolean isCompact(Collection<Triple> cluster) {
+            Node predicate = null;
             for ( Triple t : cluster ) {
                 Node p = t.getPredicate() ;
-                x.add(p) ;
+                Node o = t.getObject();
+                if ( isPrettyNode(o) )
+                    return false;
+                if ( predicate != null ) {
+                    if ( ! predicate.equals(p))
+                        // 2+ different predicates.
+                        return false ;
+                } else 
+                    predicate = p;
             }
-            return x.size() ;
+            return true;
         }
 
         // [ :p "abc" ] .  or    [] : "abc" .
@@ -817,10 +823,8 @@
                 print("[] ") ;
                 return ;
             }
-
-            int pCount = countPredicates(x) ;
-
-            if ( pCount == 1 ) {
+            
+            if ( isCompact(x) ) {
                 print("[ ") ;
                 out.incIndent(2) ;
                 writePredicateObjectList(x) ;
@@ -829,7 +833,6 @@
                 return ;
             }
 
-            // Two or more.
             int indent0 = out.getAbsoluteIndent() ;
             int here = out.getCol() ;
             out.setAbsoluteIndent(here) ;
@@ -920,6 +923,7 @@
         }
 
         private boolean isPrettyNode(Node n) {
+            // Maybe ought to be the same test as writePredicateObjectList
             // Order matters? - one connected objects may include list elements.
             if ( allowDeepPretty ) {
                 if ( lists.containsKey(n) )
@@ -964,42 +968,28 @@
     }
 
     // Order of properties.
-    // rdf:type ("a")
-    // RDF and RDFS
-    // Other.
-    // Sorted by URI.
+    //   rdf:type ("a")
+    //    RDF and RDFS
+    //    Other.
+    // Sor0ted by URI.
 
-    private static final class ComparePredicates implements Comparator<Node> {
-        private static int classification(Node p) {
-            if ( p.equals(RDF_type) )
-                return 0 ;
-
-            if ( p.getURI().startsWith(RDF.getURI()) || p.getURI().startsWith(RDFS.getURI()) )
-                return 1 ;
-
-            return 2 ;
-        }
-
-        @Override
-        public int compare(Node t1, Node t2) {
-            int class1 = classification(t1) ;
-            int class2 = classification(t2) ;
-            if ( class1 != class2 ) {
-                // Java 1.7
-                // return Integer.compare(class1, class2) ;
-                if ( class1 < class2 )
-                    return -1 ;
-                if ( class1 > class2 )
-                    return 1 ;
-                return 0 ;
-            }
-            String p1 = t1.getURI() ;
-            String p2 = t2.getURI() ;
-            return p1.compareTo(p2) ;
-        }
+    private static int classification(Node p) {
+        if ( p.equals(RDF_type) )
+            return 0 ;
+        if ( p.getURI().startsWith(RDF.getURI()) || p.getURI().startsWith(RDFS.getURI()) )
+            return 1 ;
+        return 2 ;
     }
 
-    private static Comparator<Node> compPredicates = new ComparePredicates() ;
+    private static Comparator<Node> compPredicates = (t1,t2) -> {
+        int class1 = classification(t1) ;
+        int class2 = classification(t2) ;
+        if ( class1 != class2 )
+            return Integer.compare(class1, class2) ;
+        String p1 = t1.getURI() ;
+        String p2 = t2.getURI() ;
+        return p1.compareTo(p2) ;
+    };
 
     protected final void writeNode(Node node) {
         nodeFmt.format(out, node) ;
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedWriter.java b/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedWriter.java
index c896e8a..73a3f9d 100644
--- a/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedWriter.java
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/IndentedWriter.java
@@ -384,6 +384,6 @@
 
     @Override
     public String toString() {
-        return String.format("Indent = %d : [%d, %d]", currentIndent, row, column) ;
+        return String.format("Indent = %d : Row = %d : Col = %d", currentIndent, row, column) ;
     }
 }
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ConstraintOp1.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ConstraintOp1.java
new file mode 100644
index 0000000..bafc7e8
--- /dev/null
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ConstraintOp1.java
@@ -0,0 +1,42 @@
+/*
+ * 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.shacl.engine.constraint;
+
+import org.apache.jena.atlas.io.IndentedWriter;
+import org.apache.jena.shacl.parser.Shape;
+
+/** A constraint that operates on one other constraints */
+public abstract class ConstraintOp1 extends ConstraintOp {
+    
+    protected  final Shape other;
+    
+    protected ConstraintOp1(Shape subShape) {
+        other = subShape;
+    }
+    
+    @Override
+    public void print(IndentedWriter out) {
+        out.print(toString());
+        out.ensureStartOfLine();
+        out.incIndent();
+        other.print(out);
+        out.decIndent();
+        out.ensureStartOfLine();
+    }
+}
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ConstraintOpN.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ConstraintOpN.java
new file mode 100644
index 0000000..48c25da
--- /dev/null
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ConstraintOpN.java
@@ -0,0 +1,46 @@
+/*
+ * 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.shacl.engine.constraint;
+
+import java.util.List;
+
+import org.apache.jena.atlas.io.IndentedWriter;
+import org.apache.jena.shacl.parser.Shape;
+
+/** A constraint that combines N other constraints */
+public abstract class ConstraintOpN extends ConstraintOp {
+    
+    protected  final List<Shape> others;
+    
+    protected ConstraintOpN(List<Shape> subShapes) {
+        others = subShapes;
+    }
+    
+    @Override
+    public void print(IndentedWriter out) {
+        out.print(toString());
+        out.ensureStartOfLine();
+        out.incIndent();
+        for ( Shape sub: others ) {
+            sub.print(out);
+            out.ensureStartOfLine();
+        }
+        out.decIndent();
+    }
+}
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShAnd.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShAnd.java
index 85c7047..6b9c66a 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShAnd.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShAnd.java
@@ -31,12 +31,10 @@
 import org.apache.jena.shacl.vocabulary.SHACL;
 
 /** sh:and */
-public class ShAnd extends ConstraintOp {
-
-    private List<Shape> others;
+public class ShAnd extends ConstraintOpN {
 
     public ShAnd(List<Shape> others) {
-        this.others = others;
+        super(others);
     }
 
     @Override
@@ -60,6 +58,6 @@
 
     @Override
     public String toString() {
-        return "And"+others;
+        return "And";
     }
 }
\ No newline at end of file
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShNode.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShNode.java
index 40d2d45..3a6d45d 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShNode.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShNode.java
@@ -29,11 +29,10 @@
 import org.apache.jena.shacl.vocabulary.SHACL;
 
 /** sh:node */
-public class ShNode extends ConstraintOp {
-    private Shape other;
-
+public class ShNode extends ConstraintOp1 {
+    
     public ShNode(Shape other) {
-        this.other = other;
+        super(other);
     }
 
     @Override
@@ -54,6 +53,6 @@
 
     @Override
     public String toString() {
-        return "Node["+other+"]";
+        return "Node";
     }
 }
\ No newline at end of file
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShNot.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShNot.java
index 7795040..86cc327 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShNot.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShNot.java
@@ -29,11 +29,10 @@
 import org.apache.jena.shacl.vocabulary.SHACL;
 
 /** sh:not */
-public class ShNot extends ConstraintOp {
-    private Shape other;
+public class ShNot extends ConstraintOp1 {
 
     public ShNot(Shape other) {
-        this.other = other;
+        super(other);
     }
 
     @Override
@@ -54,6 +53,6 @@
 
     @Override
     public String toString() {
-        return "Not["+other+"]";
+        return "Not";
     }
 }
\ No newline at end of file
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShOr.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShOr.java
index 144f1d1..7d6259a 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShOr.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShOr.java
@@ -31,12 +31,10 @@
 import org.apache.jena.shacl.vocabulary.SHACL;
 
 /** sh:or */
-public class ShOr extends ConstraintOp {
-
-    private List<Shape> others;
+public class ShOr extends ConstraintOpN {
 
     public ShOr(List<Shape> others) {
-        this.others = others;
+        super(others);
     }
 
     @Override
@@ -59,6 +57,6 @@
 
     @Override
     public String toString() {
-        return "Or"+others;
+        return "Or";
     }
 }
\ No newline at end of file
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShXone.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShXone.java
index 8680560..11af8f9 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShXone.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ShXone.java
@@ -31,12 +31,10 @@
 import org.apache.jena.shacl.vocabulary.SHACL;
 
 /** sh:xone */
-public class ShXone extends ConstraintOp {
-
-    private List<Shape> others;
+public class ShXone extends ConstraintOpN {
 
     public ShXone(List<Shape> others) {
-        this.others = others;
+        super(others);
     }
 
     @Override
@@ -65,6 +63,6 @@
 
     @Override
     public String toString() {
-        return "Or"+others;
+        return "Xone";
     }
 }
\ No newline at end of file
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Shape.java b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Shape.java
index e1b5925..03fd149 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Shape.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Shape.java
@@ -95,12 +95,8 @@
         if ( !(out instanceof BufferedOutputStream) )
             out = new BufferedOutputStream(out, 128 * 1024);
         IndentedWriter w = new IndentedWriter(out);
-        try {
-            print(w);
-        }
-        finally {
-            // w.flush();
-        }
+        try { print(w); }
+        finally { w.flush(); }
     }
 
     protected abstract void printHeader(IndentedWriter out);
@@ -119,7 +115,8 @@
         try {
             for ( Constraint c : constraints ) {
                 c.print(out);
-                out.println();
+                if ( ! out.atLineStart() )
+                    out.println();
             }
             for ( PropertyShape ps : getPropertyShapes() ) {
                 ps.print(out);