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/11 22:05:10 UTC

svn commit: r1432285 - in /jena/trunk/jena-arq: ReleaseNotes.txt src/main/java/com/hp/hpl/jena/sparql/path/PathLib.java src/test/java/com/hp/hpl/jena/sparql/path/TestPath.java src/test/java/com/hp/hpl/jena/sparql/path/TestPath2.java

Author: andy
Date: Fri Jan 11 21:05:09 2013
New Revision: 1432285

URL: http://svn.apache.org/viewvc?rev=1432285&view=rev
Log:
JENA-379 : Fix for property paths (when not otherwise optimized) using same variable for subject and object.

Modified:
    jena/trunk/jena-arq/ReleaseNotes.txt
    jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/path/PathLib.java
    jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/path/TestPath.java
    jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/path/TestPath2.java

Modified: jena/trunk/jena-arq/ReleaseNotes.txt
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/ReleaseNotes.txt?rev=1432285&r1=1432284&r2=1432285&view=diff
==============================================================================
--- jena/trunk/jena-arq/ReleaseNotes.txt (original)
+++ jena/trunk/jena-arq/ReleaseNotes.txt Fri Jan 11 21:05:09 2013
@@ -7,6 +7,7 @@ ChangeLog for ARQ
 
 + Consolidation of versions numbers.
 
+* JENA-379 : Incorrect results from a property paths with same subject and object variable.  
 + Introduce RDFParserOutput as output interface for parsers (was Sink<Triple> or Sink<Quad>)
 + RIOT - internal reorganisation moving to org.apache.jena.riot.
 + Remove the partial migration support for old-style SPARQL submission update forms.

Modified: jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/path/PathLib.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/path/PathLib.java?rev=1432285&r1=1432284&r2=1432285&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/path/PathLib.java (original)
+++ jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/path/PathLib.java Fri Jan 11 21:05:09 2013
@@ -22,6 +22,10 @@ import java.util.ArrayList ;
 import java.util.Iterator ;
 import java.util.List ;
 
+import org.apache.jena.atlas.iterator.Filter ;
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.lib.Lib ;
+
 import com.hp.hpl.jena.graph.Graph ;
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.ARQInternalErrorException ;
@@ -138,7 +142,12 @@ public class PathLib
         Graph graph = execCxt.getActiveGraph() ;
         
         if ( Var.isVar(s) && Var.isVar(o) )
-            return ungroundedPath(binding, graph, Var.alloc(s), path, Var.alloc(o), execCxt) ;
+        {
+            if ( s.equals(o) )
+                return ungroundedPathSameVar(binding, graph, Var.alloc(s), path, execCxt) ;
+            else
+                return ungroundedPath(binding, graph, Var.alloc(s), path, Var.alloc(o), execCxt) ;
+        }
 
         if ( ! Var.isVar(s) && ! Var.isVar(o) )
             return groundedPath(binding, graph, s, path, o, execCxt) ;
@@ -212,4 +221,37 @@ public class PathLib
         }
         return qIterCat ;
     }
+    
+    private static QueryIterator ungroundedPathSameVar(Binding binding, Graph graph, Var var, Path path, ExecutionContext execCxt)
+    {
+        // Try each end, grounded  
+        // Slightly more efficient would be to add a per-engine to do this.
+        Iterator<Node> iter = GraphUtils.allNodes(graph) ;
+        QueryIterConcat qIterCat = new QueryIterConcat(execCxt) ;
+        
+        for ( ; iter.hasNext() ; )
+        {
+            Node n = iter.next() ;
+            Binding b2 = BindingFactory.binding(binding, var, n) ;
+            int x = existsPath(graph, n, path, n) ;
+            if ( x > 0 )
+            {
+                QueryIterator qIter = new QueryIterYieldN(x, b2, execCxt) ;
+                qIterCat.add(qIter) ;
+            }
+        }
+        return qIterCat ; 
+    }
+    
+    private static int existsPath(Graph graph, Node subject, Path path, final Node object)
+    {
+        if ( ! subject.isConcrete() || !object.isConcrete() )
+            throw new ARQInternalErrorException("Non concrete node for existsPath evaluation") ;
+        Iterator<Node> iter = PathEval.eval(graph, subject, path) ;
+        Filter<Node> filter = new Filter<Node>() { @Override public boolean accept(Node node) { return Lib.equal(node,  object) ; } } ; 
+        // See if we got to the node we're interested in finishing at.
+        iter = Iter.filter(iter, filter) ;
+        long x = Iter.count(iter) ; 
+        return (int)x ;
+    }
 }

Modified: jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/path/TestPath.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/path/TestPath.java?rev=1432285&r1=1432284&r2=1432285&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/path/TestPath.java (original)
+++ jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/path/TestPath.java Fri Jan 11 21:05:09 2013
@@ -18,26 +18,29 @@
 
 package com.hp.hpl.jena.sparql.path;
 
-import static org.junit.Assert.assertEquals ;
-import static org.junit.Assert.fail ;
-
 import java.util.ArrayList ;
 import java.util.Arrays ;
 import java.util.Iterator ;
 import java.util.List ;
 
 import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.junit.BaseTest ;
 import org.junit.Assert ;
-import org.junit.Ignore ;
 import org.junit.Test ;
 
 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.ARQ ;
 import com.hp.hpl.jena.query.QueryParseException ;
 import com.hp.hpl.jena.shared.PrefixMapping ;
 import com.hp.hpl.jena.shared.impl.PrefixMappingImpl ;
 import com.hp.hpl.jena.sparql.core.Prologue ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.engine.ExecutionContext ;
+import com.hp.hpl.jena.sparql.engine.QueryIterator ;
+import com.hp.hpl.jena.sparql.engine.binding.Binding ;
+import com.hp.hpl.jena.sparql.engine.binding.BindingFactory ;
 import com.hp.hpl.jena.sparql.graph.GraphFactory ;
 import com.hp.hpl.jena.sparql.path.eval.PathEval ;
 import com.hp.hpl.jena.sparql.sse.Item ;
@@ -45,13 +48,15 @@ import com.hp.hpl.jena.sparql.sse.SSE ;
 import com.hp.hpl.jena.sparql.sse.builders.BuilderPath ;
 import com.hp.hpl.jena.sparql.sse.writers.WriterPath ;
 
-public class TestPath
+public class TestPath extends BaseTest
 {
     static Graph graph1 = GraphFactory.createDefaultGraph() ;
     static Graph graph2 = GraphFactory.createDefaultGraph() ;
     static Graph graph3 = GraphFactory.createDefaultGraph() ;
     static Graph graph4 = GraphFactory.createDefaultGraph() ;
     static Graph graph5 = GraphFactory.createDefaultGraph() ;
+    static Graph graph6 = GraphFactory.createDefaultGraph() ;
+    static Graph graph7 = GraphFactory.createDefaultGraph() ;
     
     static Node n1 = Node.createURI("n1") ;
     static Node n2 = Node.createURI("n2") ;
@@ -96,6 +101,15 @@ public class TestPath
         graph5.add(new Triple(n1, p, n3)) ;
         graph5.add(new Triple(n2, q, n4)) ;
         graph5.add(new Triple(n3, q, n5)) ;
+        
+        // Loop
+        graph6.add(new Triple(n1, p, n2)) ;
+        graph6.add(new Triple(n2, p, n1)) ;
+        
+        // Loop + tail
+        graph7.add(new Triple(n1, p, n2)) ;
+        graph7.add(new Triple(n2, p, n1)) ;
+        graph7.add(new Triple(n2, p, n3)) ;
     }
     
     // ----
@@ -235,15 +249,72 @@ public class TestPath
     @Test public void path_32()   { test(graph3, n1,   ":p{*}",     n1,n2,n3,n4,n4) ; }
     @Test public void path_33()   { test(graph3, n1,   ":p*",       n1,n2,n3,n4) ; }
     @Test public void path_34()   { test(graph3, n1,   ":p+",       n2,n3,n4) ; }
+
+    
+    private static List<Binding> eval(Graph graph, String start$, String pathStr, String finish$)
+    {
+        return eval(graph, SSE.parseNode(start$, pmap), pathStr, SSE.parseNode(finish$, pmap)) ;
+    }
+    
+    private static List<Binding> eval(Graph graph, Node start, String pathStr, Node finish)
+    {
+        Path path = SSE.parsePath(pathStr, pmap) ;
+        QueryIterator qIter = PathLib.execTriplePath(BindingFactory.root(), start, path, finish, new ExecutionContext(ARQ.getContext(), graph, null, null)) ;
+        return Iter.toList(qIter) ;
+    }
+    
+    @Test public void path_35()
+    { 
+        List<Binding> x = eval(graph6, "?x", "(path+ :p)", "?y" ) ;
+        assertEquals(4, x.size()) ;
+    }
     
+    @Test public void path_36()
+    { 
+        // Same end points.
+        List<Binding> x = eval(graph6, "?x", "(path+ :p)", "?x" ) ;
+        assertEquals(2, x.size()) ;
+    }
+
+    @Test public void path_37()
+    { 
+        List<Binding> x = eval(graph6, "?x", "(path* :p)", "?x" ) ;
+        assertEquals(2, x.size()) ;
+        Node node1 = x.get(0).get(Var.alloc("x")) ;
+        Node node2 = x.get(1).get(Var.alloc("x")) ;
+        assertFalse(node1.equals(node2)) ;
+        assertTrue(node1.equals(n1) || node1.equals(n2)) ;
+        assertTrue(node2.equals(n1) || node2.equals(n2)) ;
+    }
+
+    @Test public void path_38()
+    { 
+        // Same end points.
+        List<Binding> x = eval(graph6, "?x", "(pathN+ :p)", "?x" ) ;
+        
+        assertEquals(2, x.size()) ;
+        Node node1 = x.get(0).get(Var.alloc("x")) ;
+        Node node2 = x.get(1).get(Var.alloc("x")) ;
+        assertFalse(node1.equals(node2)) ;
+        assertTrue(node1.equals(n1) || node1.equals(n2)) ;
+        assertTrue(node2.equals(n1) || node2.equals(n2)) ;
+    }
+
+    @Test public void path_39()
+    { 
+        List<Binding> x = eval(graph6, "?x", "(pathN* :p)", "?x" ) ;
+        assertEquals(2, x.size()) ;
+    }
+
     // TODO Shortest path is not implemented yet.  These also need to be verified that they are correct.
-    @Ignore @Test public void path_40()   { test(graph1, n1,   "shortest(:p*)",       n1) ; }
-    @Ignore @Test public void path_41()   { test(graph1, n1,   "shortest(:p+)",       n2) ; }
-    @Ignore @Test public void path_42()   { test(graph2, n1,   "shortest(:p*/:q)",    n4) ; }
-    @Ignore @Test public void path_43()   { test(graph2, n1,   "shortest(:p{*}/:q)",  n4, n4) ; }
-    @Ignore @Test public void path_44()   { test(graph4, n1,   "shortest(:p*/:q)",    n5) ; }
-    @Ignore @Test public void path_45()   { test(graph4, n1,   "shortest(:p{2,}/:q)", n6) ; }
-    @Ignore @Test public void path_46()   { test(graph5, n1,   "shortest(:p*/:q)",    n4, n5) ; }
+//    @Ignore @Test public void path_40()   { test(graph1, n1,   "shortest(:p*)",       n1) ; }
+//    @Ignore @Test public void path_41()   { test(graph1, n1,   "shortest(:p+)",       n2) ; }
+//    @Ignore @Test public void path_42()   { test(graph2, n1,   "shortest(:p*/:q)",    n4) ; }
+//    @Ignore @Test public void path_43()   { test(graph2, n1,   "shortest(:p{*}/:q)",  n4, n4) ; }
+//    @Ignore @Test public void path_44()   { test(graph4, n1,   "shortest(:p*/:q)",    n5) ; }
+//    @Ignore @Test public void path_45()   { test(graph4, n1,   "shortest(:p{2,}/:q)", n6) ; }
+//    @Ignore @Test public void path_46()   { test(graph5, n1,   "shortest(:p*/:q)",    n4, n5) ; }
+    
     
 
     // ----

Modified: jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/path/TestPath2.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/path/TestPath2.java?rev=1432285&r1=1432284&r2=1432285&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/path/TestPath2.java (original)
+++ jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/path/TestPath2.java Fri Jan 11 21:05:09 2013
@@ -103,7 +103,7 @@ public class TestPath2 extends BaseTest
     @Test public void path_35() { test(x, "(pathN+ :r)",          ":y2", ":z", ":a2", ":b", ":a1", ":b", ":y1", ":z", ":a2", ":b", ":a1", ":b") ; } 
 	@Test public void path_36() { test(x, "(path* :r)",           ":x", ":y2", ":z", ":a2", ":b", ":a1", ":y1") ; } 
 	@Test public void path_37() { test(x, "(pathN* :r)",          ":x", ":y2", ":z", ":a2", ":b", ":a1", ":b", ":y1", ":z", ":a2", ":b", ":a1", ":b") ; } 
-	
+
 //	static int i = 0 ;
 	
 	private void test(Node start, String pathStr, String ... results)