Author: andy
Date: Tue Apr 16 20:17:00 2013
New Revision: 1468596

URL: http://svn.apache.org/r1468596
Log:
dev sync

Added:
    jena/Scratch/AFS/Jena-Dev/trunk/src/dev/TransformFilterEquality2.java
    
jena/Scratch/AFS/Jena-Dev/trunk/src/reports/archive/Jena437_XSDDatetypeValue.java
Removed:
    
jena/Scratch/AFS/Jena-Dev/trunk/src/reports/archive/Jena247_XSDDatimeTzBoundary.java
    jena/Scratch/AFS/Jena-Dev/trunk/src/reports/archive/xsddt_247/
Modified:
    jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JenaNNN_FilterEquality.java

Modified: jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JenaNNN_FilterEquality.java
URL: 
http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JenaNNN_FilterEquality.java?rev=1468596&r1=1468595&r2=1468596&view=diff
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JenaNNN_FilterEquality.java 
(original)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/dev/JenaNNN_FilterEquality.java Tue Apr 
16 20:17:00 2013
@@ -69,7 +69,16 @@ public class JenaNNN_FilterEquality
               , "}"
                 ) ;
 
-        String[] x = { qs1 , qs2 } ;
+        // Scoping issues : unsafe works
+        String qs3 = StrUtils.strjoinNL
+            ( "PREFIX : <http://example/> SELECT * {"
+              , "    ?z :p ?o2"              
+              , "    OPTIONAL { ?x :q ?o }"     // ?x is optional.
+              , "    FILTER(?x = :x)"
+              , "}"
+                ) ;
+
+        String[] x = { qs1 } ;
         for ( String qs : x )
         {
             Query query = QueryFactory.create(qs) ;
@@ -84,8 +93,9 @@ public class JenaNNN_FilterEquality
 //            Op op1 = TransformScopeRename.transform(op) ; 
             //        Op op1 = Transformer.transform(new 
TransformJoinStrategy(), op) ;
             //        Op op1 = Transformer.transform(new 
TransformFilterDisjunction(), op) ;
-            System.out.println("- - - - - TransformFilterEquality") ;
-            Op op1 = Transformer.transform(new TransformFilterEquality(), op) ;
+            System.out.println("- - - - - Single Transform") ;
+            Op op1 = Transformer.transform(new TransformFilterEquality2(), op) 
;
+            
             System.out.print(op1) ;
             System.out.println("- - - - - Optimize") ;
             Op op2 = Algebra.optimize(op) ; 
@@ -111,6 +121,7 @@ public class JenaNNN_FilterEquality
               , "    ?x :p ?o2"
               , "}"
                 ) ;
+        // Possible transformation:
         // Safe to transform:  This (sequence) always defined ?x 
         String ops = StrUtils.strjoinNL
             ("(assign ((?x <http://example/x>))"
@@ -120,7 +131,17 @@ public class JenaNNN_FilterEquality
             , "         (bgp (triple <http://example/x> <http://example/q> 
?o)))"
             , "       (bgp (triple <http://example/x> <http://example/p> 
?o2))))"
             ) ;
-        check(qs, ops) ;
+        // Currently :
+        String ops1 = StrUtils.strjoinNL
+            ("(filter (= ?x <http://example/x>)"
+            ,"  (sequence"
+            ,"    (conditional"
+            ,"      (table unit)"
+            ,"      (bgp (triple ?x <http://example/q> ?o)) )"
+            ,"    (bgp (triple ?x <http://example/p> ?o2)) ))"
+            ) ;
+        
+        check(qs, ops1) ;
     }
 
     // JENA-294 part II
@@ -143,15 +164,36 @@ public class JenaNNN_FilterEquality
         check(qs, ops) ;
     }
     
-    // Scope of variable (optional, defined) cases 
+    // JENA-294 part II
     @Test public void test_OptEqualityScope_03() {
         String qs = StrUtils.strjoinNL
             ( "PREFIX : <http://example/> SELECT * {"
+              , "    ?z :p ?o2"
               , "    OPTIONAL { ?x :q ?o }"
               , "    FILTER(?x = :x)"
               , "}"
                 ) ;
-        // Unsafe to transform:  This may not defined ?x, then FILTER -> 
unbound -> error -> false 
+        // Unsafe to transform:  ?x is optional. 
+        String ops = StrUtils.strjoinNL
+            ( "(filter (= ?x <http://example/x>)"
+            , "   (conditional"
+            , "     (bgp (triple ?z <http://example/p> ?o2))"
+            , "     (bgp (triple ?x <http://example/q> ?o))"
+            , "))"
+            ) ;
+        check(qs, ops) ;
+    }
+
+    // Scope of variable (optional, defined) cases 
+    @Test public void test_OptEqualityScope_04() {
+        String qs = StrUtils.strjoinNL
+            ( "PREFIX : <http://example/> SELECT * {"
+              , "    OPTIONAL { ?x :q ?o }"
+              , "    FILTER(?x = :x)"
+              , "}"
+                ) ;
+        // Unsafe to transform:  This may not defined ?x, then FILTER -> 
unbound -> error -> false
+        // But push down possible.
         String ops = StrUtils.strjoinNL
             ("(assign ((?x <http://example/x>))"
             , "   (sequence"
@@ -160,20 +202,43 @@ public class JenaNNN_FilterEquality
             , "         (bgp (triple <http://example/x> <http://example/q> 
?o)))"
             , "       (bgp (triple <http://example/x> <http://example/p> 
?o2))))"
             ) ;
-        check(qs, ops) ;
+        String ops1 = StrUtils.strjoinNL
+            ("(filter (= ?x <http://example/x>)"
+            ,"    (conditional"
+            ,"      (table unit)"
+            ,"      (assign ((?x <http://example/x>))"
+            ,"        (bgp (triple <http://example/x> <http://example/q> 
?o)))))"
+            ) ;
+        
+        check(qs, ops1) ;
     }
     
-    
+    // JENA-383
+    @Test public void test_OptEqualityScopingNested() {
+        // Can't transform: ?var not used in middle OPTIONAL.
+        String qs = StrUtils.strjoinNL
+            ( "PREFIX ex: <http://example.org/test#>"
+            , "SELECT * {"
+            , "    ?var ex:p1 ?x."
+            , "    OPTIONAL {"
+            , "        ?x ex:p2 ?y."
+            , "        OPTIONAL { ?y ex:p3 ?z }"
+            , "    }"
+            , "    FILTER (?var = ex:i)"
+            , " }"
+            ) ;
+        String ops = StrUtils.strjoinNL
+            ( "(filter (= ?var <http://example.org/test#i>)"
+            , "  (conditional"
+            , "     (bgp (triple ?var <http://example.org/test#p1> ?x))"
+            , "     (conditional"
+            , "        (bgp (triple ?x <http://example.org/test#p2> ?y))"
+            , "        (bgp (triple ?y <http://example.org/test#p3> ?z)))"
+            , " ))" 
+            ) ;
+        check(qs, ops) ;
+    }
 
-    //JENA-294 part II
-    /*
-SELECT *
-{
-?x :p ?o2
-OPTIONAL { ?x :q ?o }
-FILTER(?x = :x)
-}
- */   
     
     // JENA-432
     @Test public void test_OptEqualitySubQuery_01() {
@@ -199,34 +264,54 @@ FILTER(?x = :x)
             , "          (project (?s1)"
             , "            (bgp (triple ?s1 ?/p2 ?/o2))))))"
             ) ;
-        check(qs, ops) ;
-    }
-    
-    // JENA-432
-    @Test public void test_OptEqualitySubQuery_02() {
-        String qs = StrUtils.strjoinNL
-                ( "SELECT *",
-                  "WHERE {",
-                  "  ?test ?p1 ?o1.",
-                  "  OPTIONAL {",
-                  "    SELECT ?test",   
-                  "    { ?s1 ?p2 ?o2 }", //" GROUP BY ?s1",
-                  "  }" ,
-                  "}" ) ;             
-        String ops = StrUtils.strjoinNL
+        String ops1 = StrUtils.strjoinNL
             ( "(disjunction"
             , "  (assign ((?test <http://localhost/t1>))"
-            , "      (conditional"
+            , "      (leftjoin"
             , "          (bgp (triple <http://localhost/t1> ?p1 ?o1))"
             , "          (project (?s1)"
             , "            (bgp (triple ?s1 ?/p2 ?/o2)))))"
             , "      (assign ((?test <http://localhost/t2>))"
-            , "        (conditional"
+            , "        (leftjoin"
             , "          (bgp (triple <http://localhost/t2> ?p1 ?o1))"
             , "          (project (?s1)"
             , "            (bgp (triple ?s1 ?/p2 ?/o2))))))"
             ) ;
+
+        check(qs, ops1) ;
+    }
+    
+    @Test public void test_OptSubQuery_01() {
+        String qs = StrUtils.strjoinNL
+            ( "SELECT *"
+            , "WHERE {"
+            , "    ?test ?p1 ?X." 
+            , "    { SELECT ?s1 ?test { ?test ?p2 ?o2 } }"
+            , "}") ; 
         
+        String ops = StrUtils.strjoinNL
+            ("(sequence"
+            ,"  (bgp (triple ?test ?p1 ?X))"
+            ,"  (project (?s1 ?test)"
+            ,"    (bgp (triple ?test ?/p2 ?/o2))))"
+            ) ;
+        check(qs, ops) ;
+    }
+
+    @Test public void test_OptSubQuery_02() {
+        String qs = StrUtils.strjoinNL
+            ( "SELECT *"
+            , "WHERE {"
+            , "    ?test ?p1 ?X." 
+            , "    { SELECT ?s1 { ?test ?p2 ?o2 } }"
+            , "}") ; 
+        
+        String ops = StrUtils.strjoinNL
+            ("(sequence"
+            ,"  (bgp (triple ?test ?p1 ?X))"
+            ,"  (project (?s1)"
+            ,"    (bgp (triple ?test ?/p2 ?/o2))))"
+            ) ;
         check(qs, ops) ;
     }
 
@@ -241,17 +326,11 @@ FILTER(?x = :x)
             , "}") ; 
         
         String ops = StrUtils.strjoinNL
-            ( "(disjunction"
-            , "  (assign ((?test <http://localhost/t1>))"
-            , "      (conditional"
-            , "          (bgp (triple <http://localhost/t1> ?p1 ?o1))"
-            , "          (project (?s1)"
-            , "            (bgp (triple ?s1 ?/p2 ?/o2)))))"
-            , "      (assign ((?test <http://localhost/t2>))"
-            , "        (conditional"
-            , "          (bgp (triple <http://localhost/t2> ?p1 ?o1))"
-            , "          (project (?s1)"
-            , "            (bgp (triple ?s1 ?/p2 ?/o2))))))"
+            ("(filter (= ?test <http://localhost/t1>)"
+            ,"    (join"
+            ,"      (bgp (triple ?test ?p1 ?X))"
+            ,"      (project (?s1 ?test)"
+            ,"        (bgp (triple ?test ?/p2 ?/o2)))))"
             ) ;
         check(qs, ops) ;
     }
@@ -266,17 +345,11 @@ FILTER(?x = :x)
             , "    { SELECT ?s1 { ?test ?p2 ?o2 } }"
             , "}") ;
         String ops = StrUtils.strjoinNL
-            ( "(disjunction"
-            , "  (assign ((?test <http://localhost/t1>))"
-            , "      (conditional"
-            , "          (bgp (triple <http://localhost/t1> ?p1 ?o1))"
-            , "          (project (?s1)"
-            , "            (bgp (triple ?s1 ?/p2 ?/o2)))))"
-            , "      (assign ((?test <http://localhost/t2>))"
-            , "        (conditional"
-            , "          (bgp (triple <http://localhost/t2> ?p1 ?o1))"
-            , "          (project (?s1)"
-            , "            (bgp (triple ?s1 ?/p2 ?/o2))))))"
+            ( "  (assign ((?test <http://localhost/t1>))"
+            , "    (join"
+            , "       (bgp (triple <http://localhost/t1> ?p1 ?X))"
+            , "       (project (?s1)"
+            , "         (bgp (triple ?/test ?/p2 ?/o2))) ))"
             ) ;
         
         check(qs, ops) ;
@@ -294,44 +367,18 @@ FILTER(?x = :x)
               , "}"
                 ) ;
         String ops = StrUtils.strjoinNL
-            ( "(filter (= ?var <http://example.org/test#i>)"
-            , "  (conditional"
-            , "     (bgp (triple ?var <http://example.org/test#p1> ?x))"
-            , "        (conditional"
-            , "           (bgp (triple ?x <http://example.org/test#p2> ?y))"
-            , "           (bgp (triple ?y <http://example.org/test#p3> ?z)))"
+            ( "(filter (= ?x <http://example/x>)"
+            , "  (sequence"
+            , "     (conditional"
+            , "        (table unit)"
+            , "        (bgp (triple ?x <http://example/q> ?o)))"
+            , "     (bgp (triple ?x <http://example/p> ?o2))"
             , " ))" 
             ) ;
         check(qs, ops) ;
     }
 
         
-  
-    // JENA-383
-    @Test public void test_OptEqualityScopingNested() {
-        // Can't transform: ?var not used in middle OPTIONAL.
-        String qs = StrUtils.strjoinNL
-            ( "PREFIX ex: <http://example.org/test#>"
-            , "SELECT * {"
-            , "    ?var ex:p1 ?x."
-            , "    OPTIONAL {"
-            , "        ?x ex:p2 ?y."
-            , "        OPTIONAL { ?y ex:p3 ?z }"
-            , "    }"
-            , "    FILTER (?var = ex:i)"
-            , " }"
-            ) ;
-        String ops = StrUtils.strjoinNL
-            ( "(filter (= ?var <http://example.org/test#i>)"
-            , "  (conditional"
-            , "     (bgp (triple ?var <http://example.org/test#p1> ?x))"
-            , "     (conditional"
-            , "        (bgp (triple ?x <http://example.org/test#p2> ?y))"
-            , "        (bgp (triple ?y <http://example.org/test#p3> ?z)))"
-            , " ))" 
-            ) ;
-        check(qs, ops) ;
-        }
 
     
 
@@ -352,6 +399,7 @@ FILTER(?x = :x)
             System.out.print(opExpected) ;
             System.out.println("*** Actual") ;
             System.out.print(opOptimize) ;
+            System.out.println() ;
         }
         Assert.assertEquals(opExpected, opOptimize) ;
         

Added: jena/Scratch/AFS/Jena-Dev/trunk/src/dev/TransformFilterEquality2.java
URL: 
http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/dev/TransformFilterEquality2.java?rev=1468596&view=auto
==============================================================================
--- jena/Scratch/AFS/Jena-Dev/trunk/src/dev/TransformFilterEquality2.java 
(added)
+++ jena/Scratch/AFS/Jena-Dev/trunk/src/dev/TransformFilterEquality2.java Tue 
Apr 16 20:17:00 2013
@@ -0,0 +1,405 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dev;
+
+import static org.apache.jena.atlas.lib.CollectionUtils.disjoint ;
+
+import java.util.ArrayList ;
+import java.util.Collection ;
+import java.util.List ;
+import java.util.Set ;
+
+import org.apache.jena.atlas.lib.Pair ;
+
+import com.hp.hpl.jena.query.ARQ ;
+import com.hp.hpl.jena.sparql.algebra.Op ;
+import com.hp.hpl.jena.sparql.algebra.OpVars ;
+import com.hp.hpl.jena.sparql.algebra.TransformCopy ;
+import com.hp.hpl.jena.sparql.algebra.op.* ;
+import com.hp.hpl.jena.sparql.core.Substitute ;
+import com.hp.hpl.jena.sparql.core.Var ;
+import com.hp.hpl.jena.sparql.core.VarExprList ;
+import com.hp.hpl.jena.sparql.engine.main.VarFinder ;
+import com.hp.hpl.jena.sparql.expr.* ;
+
+public class TransformFilterEquality2 extends TransformCopy
+{
+    // The approach taken for { OPTIONAL{} OPTIONAL{} } is more general ... 
and better?
+    // Still need to be careful of double-nested OPTIONALS as intermedates of 
a different
+    // value can block overall results so don't mask immediately.
+    public TransformFilterEquality2()
+    { }
+    
+    @Override
+    public Op transform(OpFilter opFilter, Op subOp)
+    {
+        Op op = apply(opFilter.getExprs(), subOp) ;
+        if ( op == null )
+            return super.transform(opFilter, subOp) ;
+        return op ;
+    }
+    
+    private static Op apply(ExprList exprs, Op subOp)
+    {
+        // ---- Find and extract any equality filters.
+        Pair<List<Pair<Var, NodeValue>>, ExprList> p = 
preprocessFilterEquality(exprs) ;
+        if ( p == null || p.getLeft().size() == 0 )
+            return null ;
+        
+        List<Pair<Var, NodeValue>> equalities = p.getLeft() ;
+        Collection<Var> varsMentioned = 
varsMentionedInEqualityFilters(equalities) ;
+        ExprList remaining = p.getRight() ;
+        
+        // ---- Check if the subOp is the right shape to transform.
+        Op op = subOp ;
+        
+        // Special case : deduce that the filter will always "eval unbound"
+        // hence elimate all rows.  Return the empty table. 
+        
+        if ( testSpecialCaseUnused(subOp, equalities, remaining))
+            return OpTable.empty() ;
+        
+        // Special case: the deep left op of a OpConditional/OpLeftJoin is 
unit table.
+        // This is 
+        // { OPTIONAL{P1} OPTIONAL{P2} ... FILTER(?x = :x) } 
+        if ( testSpecialCase1(subOp, equalities, remaining))
+        {
+            // Find backbone of ops
+            List<Op> ops = extractOptionals(subOp) ;
+            ops = processSpecialCase1(ops, equalities) ;
+            // Put back together
+            op = rebuild((Op2)subOp, ops) ;
+            // Put all filters - either we optimized, or we left alone.
+            // Either way, the complete set of filter expressions.
+            op = OpFilter.filter(exprs, op) ;
+            return op ;
+        }
+        
+        // ---- Transform
+
+        if ( ! safeToTransform(varsMentioned, op) )
+            return null ;
+        for ( Pair<Var, NodeValue> equalityTest : equalities )
+            op = processFilterWorker(op, equalityTest.getLeft(), 
equalityTest.getRight()) ;
+
+        // ---- Place any filter expressions around the processed sub op. 
+        if ( remaining.size() > 0 )
+            op = OpFilter.filter(remaining, op) ;
+        return op ;
+    }
+
+    // --- find and extract 
+    private static Pair<List<Pair<Var, NodeValue>>, ExprList> 
preprocessFilterEquality(ExprList exprs)
+    {
+        List<Pair<Var, NodeValue>> exprsFilterEquality = new 
ArrayList<Pair<Var, NodeValue>>() ;
+        ExprList exprsOther = new ExprList() ;
+        for ( Expr e : exprs.getList() )
+        {
+            Pair<Var, NodeValue> p = preprocess(e) ;
+            if ( p != null )
+                exprsFilterEquality.add(p) ;
+            else
+                exprsOther.add(e) ;
+        }
+        if ( exprsFilterEquality.size() == 0 )
+            return null ;
+        return Pair.create(exprsFilterEquality, exprsOther) ;
+    }
+    
+    private static Pair<Var, NodeValue> preprocess(Expr e)
+    {
+        if ( !(e instanceof E_Equals) && !(e instanceof E_SameTerm) )
+            return null ;
+
+        ExprFunction2 eq = (ExprFunction2)e ;
+        Expr left = eq.getArg1() ;
+        Expr right = eq.getArg2() ;
+
+        Var var = null ;
+        NodeValue constant = null ;
+
+        if ( left.isVariable() && right.isConstant() )
+        {
+            var = left.asVar() ;
+            constant = right.getConstant() ;
+        }
+        else if ( right.isVariable() && left.isConstant() )
+        {
+            var = right.asVar() ;
+            constant = left.getConstant() ;
+        }
+
+        if ( var == null || constant == null )
+            return null ;
+
+        // Corner case: sameTerm is false for string/plain literal, 
+        // but true in the graph for graph matching. 
+        if (e instanceof E_SameTerm)
+        {
+            if ( ! ARQ.isStrictMode() && constant.isString() )
+                return null ;
+        }
+        
+        // Final check for "=" where a FILTER = can do value matching when the 
graph does not.
+        if ( e instanceof E_Equals )
+        {
+            // Value based?
+            if ( ! ARQ.isStrictMode() && constant.isLiteral() )
+                return null ;
+        }
+        
+        return Pair.create(var, constant) ;
+    }
+
+    private static Collection<Var> 
varsMentionedInEqualityFilters(List<Pair<Var, NodeValue>> equalities)
+    {
+        List<Var> vars = new ArrayList<Var>() ;
+        for ( Pair<Var, NodeValue> p : equalities )
+            vars.add(p.getLeft()) ;
+        return vars ;
+    }
+
+    private static boolean safeToTransform(Collection<Var> varsEquality, Op op)
+    {
+        // Structure as a visitor?
+        if ( op instanceof OpBGP || op instanceof OpQuadPattern )
+            return true ;
+        
+        if ( op instanceof OpFilter )
+        {
+            OpFilter opf = (OpFilter)op ;
+            // Expressions are always safe transform by substitution.
+//            Collection<Var> fvars = opf.getExprs().getVarsMentioned() ;
+//            if ( ! disjoint(fvars, varsEquality) )
+//                return false ;
+            return safeToTransform(varsEquality, opf.getSubOp()) ;
+        }
+        
+        // This will be applied also in sub-calls of the Transform but queries 
+        // are very rarely so deep that it matters. 
+        if ( op instanceof OpSequence )
+        {
+            OpN opN = (OpN)op ;
+            for ( Op subOp : opN.getElements() )
+            {
+                if ( ! safeToTransform(varsEquality, subOp) )
+                    return false ;
+            }
+            return true ; 
+        }
+        
+        if ( op instanceof OpJoin || op instanceof OpUnion)
+        {
+            Op2 op2 = (Op2)op ;
+            
+            VarFinder vf = new VarFinder(op) ;
+            System.out.println("**** Join") ;
+            System.out.println("fixed:  "+vf.getFixed()) ;
+            System.out.println("opt:    "+vf.getOpt()) ;
+            System.out.println("filter: "+vf.getFilter()) ;
+            
+            return safeToTransform(varsEquality, op2.getLeft()) && 
safeToTransform(varsEquality, op2.getRight()) ; 
+        }
+
+        // Not safe unless filter variables are mentioned on the LHS. 
+        if ( op instanceof OpConditional || op instanceof OpLeftJoin )
+        {
+            Op2 opleftjoin = (Op2)op ;
+
+            VarFinder vf = new VarFinder(op) ;
+            System.out.println("**** LeftJoin") ;
+            System.out.println("fixed:  "+vf.getFixed()) ;
+            System.out.println("opt:    "+vf.getOpt()) ;
+            System.out.println("filter: "+vf.getFilter()) ;
+            
+            if ( ! safeToTransform(varsEquality, opleftjoin.getLeft()) || 
+                 ! safeToTransform(varsEquality, opleftjoin.getRight()) )
+                return false ;
+            
+            // Not only must the left and right be safe to transform,
+            // but the equality variable must be known to be always set. 
+
+            // If the varsLeft are disjoint from assigned vars,
+            // we may be able to push assign down right
+            // (this generalises the unit table case specialcase1)
+            // Needs more investigation.
+            
+            Op opLeft = opleftjoin.getLeft() ;
+            Set<Var> varsLeft = OpVars.visibleVars(opLeft) ;
+            if ( varsLeft.containsAll(varsEquality) )
+                return true ;
+            return false ;
+        }        
+        
+        if ( op instanceof OpGraph )
+        {
+            OpGraph opg = (OpGraph)op ;
+            return safeToTransform(varsEquality, opg.getSubOp()) ;
+        }
+        
+        // Subquery - assume scope rewriting has already been applied.  
+        if ( op instanceof OpModifier )
+        {
+            // ORDER BY?
+            OpModifier opMod = (OpModifier)op ;
+            if ( opMod instanceof OpProject )
+            {
+                OpProject opProject = (OpProject)op ;
+                // Writing "SELECT ?var" for "?var" -> a value would need 
AS-ification.
+                for ( Var v : opProject.getVars() )
+                {
+                    if ( varsEquality.contains(v) )
+                        return false ;
+                }
+            }
+            return safeToTransform(varsEquality, opMod.getSubOp()) ;
+        }
+                
+        if ( op instanceof OpGroup )
+        {
+            OpGroup opGroup = (OpGroup)op ;
+            VarExprList varExprList = opGroup.getGroupVars() ;
+            return safeToTransform(varsEquality, varExprList) && 
+                   safeToTransform(varsEquality, opGroup.getSubOp()) ;
+        }
+        
+        if ( op instanceof OpTable )
+        {
+            OpTable opTable = (OpTable)op ;
+            if ( opTable.isJoinIdentity() )
+                return true ;
+        }
+
+        // Op1 - OpGroup
+        // Op1 - OpOrder
+        // Op1 - OpAssign, OpExtend
+        // Op1 - OpFilter - done.
+        // Op1 - OpLabel - easy
+        // Op1 - OpService - no.
+        
+        return false ;
+    }
+    
+    private static boolean safeToTransform(Collection<Var> varsEquality, 
VarExprList varsExprList)
+    {
+        // If the named variable is used, unsafe to rewrite.
+        return disjoint(varsExprList.getVars(), varsEquality) ;
+    }
+    
+    // -- A special case
+
+    private static boolean testSpecialCaseUnused(Op op, List<Pair<Var, 
NodeValue>> equalities, ExprList remaining)
+    {
+        // If the op does not contain the var at all, for some equality
+        // then the filter expression will be "eval unbound" i.e. false.
+        // We can return empty table.
+        Set<Var> patternVars = OpVars.visibleVars(op) ;
+        for ( Pair<Var, NodeValue> p : equalities )
+        {
+            if ( ! patternVars.contains(p.getLeft()))
+                return true ;
+        }
+        return false ;
+    }
+    
+    // If a sequence of OPTIONALS, and nothing prior to the first, we end up 
with
+    // a unit table on the left sid of a next of LeftJoin/conditionals.
+
+    private static boolean testSpecialCase1(Op op, List<Pair<Var, NodeValue>> 
equalities , ExprList remaining )
+    {
+        while ( op instanceof OpConditional || op instanceof OpLeftJoin )
+        {
+            Op2 opleftjoin2 = (Op2)op ;
+            op = opleftjoin2.getLeft() ;
+        }
+        return isUnitTable(op) ;
+    }
+    
+    private static List<Op> extractOptionals(Op op)
+    {
+        List<Op> chain = new ArrayList<Op>() ;
+        while ( op instanceof OpConditional || op instanceof OpLeftJoin )
+        {
+            Op2 opleftjoin2 = (Op2)op ;
+            chain.add(opleftjoin2.getRight()) ;
+            op = opleftjoin2.getLeft() ;
+        }
+        return chain ;
+    }
+
+    private static List<Op> processSpecialCase1(List<Op> ops, List<Pair<Var, 
NodeValue>> equalities)
+    {
+        List<Op> ops2 = new ArrayList<Op>() ;
+        Collection<Var> vars = varsMentionedInEqualityFilters(equalities) ;
+        
+        for ( Op op : ops )
+        {
+            Op op2 = op ;
+            if ( safeToTransform(vars, op) )
+            {
+                for ( Pair<Var, NodeValue> p : equalities )
+                        op2 = processFilterWorker(op, p.getLeft(), 
p.getRight()) ;
+            }
+            ops2.add(op2) ;
+        }
+        return ops2 ;
+    }
+
+    private static Op rebuild(Op2 subOp, List<Op> ops)
+    {
+        Op chain = OpTable.unit() ; 
+        for ( Op op : ops )
+        {
+            chain = subOp.copy(chain, op) ;
+        }
+        return chain ;
+    }
+  
+    private static boolean isUnitTable(Op op)
+    {
+        if (op instanceof OpTable )
+        {
+            if ( ((OpTable)op).isJoinIdentity() )
+                return true;  
+        }
+        return false ;
+    }
+    
+    // ---- Transformation
+        
+    private static Op processFilterWorker(Op op, Var var, NodeValue constant)
+    {
+        return subst(op, var, constant) ;
+    }
+    
+    private static Op subst(Op subOp , Var var, NodeValue nv)
+    {
+        Op op = Substitute.substitute(subOp, var, nv.asNode()) ;
+        return OpAssign.assign(op, var, nv) ;
+    }
+    
+    // Helper for TransformFilterDisjunction.
+    
+    /** Apply the FilterEquality transform or return null if no change */
+
+    static Op processFilter(Expr e, Op subOp)
+    {
+        return apply(new ExprList(e), subOp) ;
+    }
+}

Added: 
jena/Scratch/AFS/Jena-Dev/trunk/src/reports/archive/Jena437_XSDDatetypeValue.java
URL: 
http://svn.apache.org/viewvc/jena/Scratch/AFS/Jena-Dev/trunk/src/reports/archive/Jena437_XSDDatetypeValue.java?rev=1468596&view=auto
==============================================================================
--- 
jena/Scratch/AFS/Jena-Dev/trunk/src/reports/archive/Jena437_XSDDatetypeValue.java
 (added)
+++ 
jena/Scratch/AFS/Jena-Dev/trunk/src/reports/archive/Jena437_XSDDatetypeValue.java
 Tue Apr 16 20:17:00 2013
@@ -0,0 +1,113 @@
+/**
+ * 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 reports.archive;
+
+import java.util.Calendar ;
+import java.util.GregorianCalendar ;
+import java.util.Locale ;
+
+import org.junit.Assert ;
+
+import com.hp.hpl.jena.datatypes.xsd.XSDDateTime ;
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.rdf.model.Literal ;
+import com.hp.hpl.jena.rdf.model.ResourceFactory ;
+import com.hp.hpl.jena.tdb.store.NodeId ;
+
+public class Jena437_XSDDatetypeValue
+{
+
+    public static void main(String[] args)
+    {
+        // There are multiple ways to represent internally
+        // the same XSDDateTime value in the millisecond/scale part.
+        // (500,3) = (5,1) so XSDDateTime objects are different
+        
+        // But LiteralLabelImpl uses lexical form for .equals
+        // but value for .hashCode.  Wrong.
+        
+        // Either canonicalize the value (contract: same value => same 
hashcode) 
+        // or use lexical form in  LiteralLabelIMpl.hashCode
+        
+        // Is it because the lexical form is in-sensitive to scale? 5.1 and 
5.100 
+        
+        // XSDDateTime.convertCalendar disagrees with parsing.
+        
+        Calendar cal=GregorianCalendar.getInstance();
+        cal.setTimeInMillis(1366126807300L);
+        //String lex = "2013-04-16T15:40:07.3Z" ;
+        
+        Literal lit1 = ResourceFactory.createTypedLiteral(cal) ;
+        Literal lit2 = 
ResourceFactory.createTypedLiteral(lit1.getLexicalForm(), lit1.getDatatype()) ;
+        
+        System.out.println(lit1) ;
+        System.out.println(lit2) ;
+
+        Assert.assertEquals(lit1, lit2) ;
+        Assert.assertEquals("hash code: ", lit1.hashCode(), lit2.hashCode()); 
+    }
+    
+    // Alt version of XSDDateTime.hashCode -- also check .equals.
+
+//    public int hashCode() {
+//        int hash = 0;
+//        // Components except fractional seconds. 
+//        for (int i = 0; i < data.length; i++) {
+//            if ( i == ms || i == msscale )
+//                // Skip fractional milliseconds
+//                continue ;
+//            hash = (hash << 1) ^ data[i];
+//        }
+//        // Slots 6,8 - use the fractional seconds and scale.
+//        //hash = (hash << 1) ^ (int)fractionalSeconds ;
+//        return hash ;
+//    }
+//  
+    
+
+    //@Test 
+    public void nodeId_dateTime_19()
+    { 
+        // This is really a check of jena-core XSDDateTime.hashCode but TDB 
NodeIds
+        // change the scale but not the value and hence best test the 
XSDDateTime.hashCode.  
+        Calendar cal = GregorianCalendar.getInstance(Locale.UK) ;
+        cal.setTimeInMillis(1366126807300L);
+        
+        Literal literal = ResourceFactory.createTypedLiteral(cal) ;
+        Node n1 = literal.asNode() ;
+        XSDDateTime dt1 = (XSDDateTime)n1.getLiteralValue() ;
+        NodeId nid = NodeId.inline(n1) ;
+        Node n2 = NodeId.extract(nid) ;
+        
+        Object v1 = n1.getLiteralValue() ;
+        Object v2 = n2.getLiteralValue() ;
+        
+        
+        
+        n1.sameValueAs(n2) ;
+        
+        v1.equals(v2) ;
+        
+        Assert.assertTrue(".sameValueAs: ", n1.sameValueAs(n2)) ;
+        Assert.assertEquals(".hashCode: ", v1.hashCode(), v2.hashCode()) ;
+        
+    }
+    
+}
+


Reply via email to