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 2012/02/10 20:53:38 UTC

svn commit: r1242901 - in /incubator/jena/Jena2/ARQ/trunk: ./ Grammar/ src/main/java/com/hp/hpl/jena/sparql/lang/arq/ src/main/java/com/hp/hpl/jena/sparql/lang/sparql_11/ src/main/java/com/hp/hpl/jena/sparql/path/ src/main/java/com/hp/hpl/jena/sparql/s...

Author: andy
Date: Fri Feb 10 19:53:38 2012
New Revision: 1242901

URL: http://svn.apache.org/viewvc?rev=1242901&view=rev
Log:
Add distinct() for path evaluation (ARQ language, not SPARQL 1.1)
Simple first implementation - no optimizations.

Added:
    incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/P_Distinct.java
Removed:
    incubator/jena/Jena2/ARQ/trunk/Q.rq
Modified:
    incubator/jena/Jena2/ARQ/trunk/Grammar/arq.jj
    incubator/jena/Jena2/ARQ/trunk/Grammar/master.jj
    incubator/jena/Jena2/ARQ/trunk/Grammar/sparql_11.jj
    incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/arq/ARQParser.java
    incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/sparql_11/SPARQLParser11.java
    incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathBase.java
    incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathEval.java
    incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathEval_ARQ.java
    incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathFactory.java
    incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathVisitor.java
    incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathWriter.java
    incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/sse/builders/BuilderPath.java
    incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/sse/writers/WriterPath.java
    incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/path/TestPath.java

Modified: incubator/jena/Jena2/ARQ/trunk/Grammar/arq.jj
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/Grammar/arq.jj?rev=1242901&r1=1242900&r2=1242901&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/Grammar/arq.jj (original)
+++ incubator/jena/Jena2/ARQ/trunk/Grammar/arq.jj Fri Feb 10 19:53:38 2012
@@ -1029,8 +1029,13 @@ Path PathPrimary() : { String str ; Path
      { p = PathFactory.pathLink(nRDFtype) ; }
   | <BANG> p = PathNegatedPropertySet()
   | <LPAREN> p = Path() <RPAREN>
+  |
+     <DISTINCT><LPAREN>
+     p = Path()
+     { p = PathFactory.pathDistinct(p) ; }
+     <RPAREN>
   )
-    { return p ; }
+ { return p ; }
 }
 Path PathNegatedPropertySet() : { P_Path0 p ; P_NegPropSet pNegSet ; }
 {

Modified: incubator/jena/Jena2/ARQ/trunk/Grammar/master.jj
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/Grammar/master.jj?rev=1242901&r1=1242900&r2=1242901&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/Grammar/master.jj (original)
+++ incubator/jena/Jena2/ARQ/trunk/Grammar/master.jj Fri Feb 10 19:53:38 2012
@@ -1201,7 +1201,7 @@ Path PathUnit() : { Path p ; }
 
 // Weakest outermost
 Path Path() : { Path p ; }
-{ 
+{
   p = PathAlternative() { return p ; }
 }
 
@@ -1286,8 +1286,15 @@ Path PathPrimary() : { String str ; Path
      { p = PathFactory.pathLink(nRDFtype) ; }
   | <BANG> p = PathNegatedPropertySet()
   | <LPAREN> p = Path() <RPAREN>
+#ifdef ARQ
+  |
+     <DISTINCT><LPAREN> 
+     p = Path()
+     { p = PathFactory.pathDistinct(p) ; }
+     <RPAREN>
+#endif
   )
-    { return p ; }
+ { return p ; }
 }
 
 Path PathNegatedPropertySet() : { P_Path0 p ; P_NegPropSet pNegSet ; }
@@ -1994,8 +2001,8 @@ SKIP : { " " | "\t" | "\n" | "\r" | "\f"
 SPECIAL_TOKEN :
 { <SINGLE_LINE_COMMENT: "#" (~["\n","\r"])* ("\n"|"\r"|"\r\n")? > }
 
-#ifdef 0
-// DSSABLED
+#if 0
+// DISABLED
 // C-style comments (they don't nest /* /*...*/ */ is a syntax error)
 // When a /* is seen in the DEFAULT state, skip it and switch to the IN_COMMENT state
 SKIP : { "/*": IN_COMMENT }

Modified: incubator/jena/Jena2/ARQ/trunk/Grammar/sparql_11.jj
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/Grammar/sparql_11.jj?rev=1242901&r1=1242900&r2=1242901&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/Grammar/sparql_11.jj (original)
+++ incubator/jena/Jena2/ARQ/trunk/Grammar/sparql_11.jj Fri Feb 10 19:53:38 2012
@@ -945,7 +945,7 @@ Path PathPrimary() : { String str ; Path
   | <BANG> p = PathNegatedPropertySet()
   | <LPAREN> p = Path() <RPAREN>
   )
-    { return p ; }
+ { return p ; }
 }
 Path PathNegatedPropertySet() : { P_Path0 p ; P_NegPropSet pNegSet ; }
 {

Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/arq/ARQParser.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/arq/ARQParser.java?rev=1242901&r1=1242900&r2=1242901&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/arq/ARQParser.java (original)
+++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/arq/ARQParser.java Fri Feb 10 19:53:38 2012
@@ -2985,6 +2985,7 @@ public class ARQParser extends ARQParser
     case PNAME_NS:
     case PNAME_LN:
     case KW_A:
+    case DISTINCT:
     case LPAREN:
     case BANG:
     case CARAT:
@@ -3019,6 +3020,7 @@ public class ARQParser extends ARQParser
       case VAR1:
       case VAR2:
       case KW_A:
+      case DISTINCT:
       case LPAREN:
       case BANG:
       case CARAT:
@@ -3027,6 +3029,7 @@ public class ARQParser extends ARQParser
         case PNAME_NS:
         case PNAME_LN:
         case KW_A:
+        case DISTINCT:
         case LPAREN:
         case BANG:
         case CARAT:
@@ -3183,6 +3186,7 @@ public class ARQParser extends ARQParser
     case PNAME_NS:
     case PNAME_LN:
     case KW_A:
+    case DISTINCT:
     case LPAREN:
     case BANG:
       p = PathElt();
@@ -3294,12 +3298,19 @@ public class ARQParser extends ARQParser
       p = Path();
       jj_consume_token(RPAREN);
       break;
+    case DISTINCT:
+      jj_consume_token(DISTINCT);
+      jj_consume_token(LPAREN);
+      p = Path();
+       p = PathFactory.pathDistinct(p) ;
+      jj_consume_token(RPAREN);
+      break;
     default:
       jj_la1[116] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
     }
-      {if (true) return p ;}
+   {if (true) return p ;}
     throw new Error("Missing return statement in function");
   }
 
@@ -5218,51 +5229,6 @@ public class ARQParser extends ARQParser
     finally { jj_save(3, xla); }
   }
 
-  private boolean jj_3R_79() {
-    if (jj_scan_token(VERSION)) return true;
-    if (jj_scan_token(NIL)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_78() {
-    if (jj_scan_token(SHA512)) return true;
-    if (jj_scan_token(LPAREN)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_149() {
-    if (jj_scan_token(STRING_LITERAL_LONG2)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_77() {
-    if (jj_scan_token(SHA384)) return true;
-    if (jj_scan_token(LPAREN)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_148() {
-    if (jj_scan_token(STRING_LITERAL_LONG1)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_76() {
-    if (jj_scan_token(SHA256)) return true;
-    if (jj_scan_token(LPAREN)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_147() {
-    if (jj_scan_token(STRING_LITERAL2)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_75() {
-    if (jj_scan_token(SHA1)) return true;
-    if (jj_scan_token(LPAREN)) return true;
-    return false;
-  }
-
   private boolean jj_3R_146() {
     if (jj_scan_token(STRING_LITERAL1)) return true;
     return false;
@@ -5675,11 +5641,6 @@ public class ARQParser extends ARQParser
     return false;
   }
 
-  private boolean jj_3_1() {
-    if (jj_3R_35()) return true;
-    return false;
-  }
-
   private boolean jj_3R_96() {
     if (jj_scan_token(LPAREN)) return true;
     return false;
@@ -5696,6 +5657,11 @@ public class ARQParser extends ARQParser
     return false;
   }
 
+  private boolean jj_3_1() {
+    if (jj_3R_35()) return true;
+    return false;
+  }
+
   private boolean jj_3R_44() {
     if (jj_scan_token(URI)) return true;
     if (jj_scan_token(LPAREN)) return true;
@@ -5956,53 +5922,47 @@ public class ARQParser extends ARQParser
     return false;
   }
 
-  private boolean jj_3R_94() {
-    if (jj_3R_105()) return true;
-    return false;
-  }
-
   private boolean jj_3R_112() {
     if (jj_scan_token(GROUP_CONCAT)) return true;
     if (jj_scan_token(LPAREN)) return true;
     return false;
   }
 
-  private boolean jj_3R_36() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_93()) {
-    jj_scanpos = xsp;
-    if (jj_3R_94()) return true;
-    }
+  private boolean jj_3R_111() {
+    if (jj_scan_token(SAMPLE)) return true;
+    if (jj_scan_token(LPAREN)) return true;
     return false;
   }
 
-  private boolean jj_3R_93() {
-    if (jj_3R_104()) return true;
+  private boolean jj_3R_94() {
+    if (jj_3R_105()) return true;
     return false;
   }
 
-  private boolean jj_3R_111() {
-    if (jj_scan_token(SAMPLE)) return true;
+  private boolean jj_3R_110() {
+    if (jj_scan_token(AVG)) return true;
     if (jj_scan_token(LPAREN)) return true;
     return false;
   }
 
-  private boolean jj_3R_110() {
-    if (jj_scan_token(AVG)) return true;
+  private boolean jj_3R_109() {
+    if (jj_scan_token(MAX)) return true;
     if (jj_scan_token(LPAREN)) return true;
     return false;
   }
 
-  private boolean jj_3_3() {
-    if (jj_scan_token(DOT)) return true;
-    if (jj_3R_36()) return true;
+  private boolean jj_3R_36() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_93()) {
+    jj_scanpos = xsp;
+    if (jj_3R_94()) return true;
+    }
     return false;
   }
 
-  private boolean jj_3R_109() {
-    if (jj_scan_token(MAX)) return true;
-    if (jj_scan_token(LPAREN)) return true;
+  private boolean jj_3R_93() {
+    if (jj_3R_104()) return true;
     return false;
   }
 
@@ -6018,6 +5978,12 @@ public class ARQParser extends ARQParser
     return false;
   }
 
+  private boolean jj_3_3() {
+    if (jj_scan_token(DOT)) return true;
+    if (jj_3R_36()) return true;
+    return false;
+  }
+
   private boolean jj_3R_106() {
     if (jj_scan_token(COUNT)) return true;
     if (jj_scan_token(LPAREN)) return true;
@@ -6049,14 +6015,20 @@ public class ARQParser extends ARQParser
     return false;
   }
 
+  private boolean jj_3R_103() {
+    if (jj_scan_token(NOT)) return true;
+    if (jj_scan_token(EXISTS)) return true;
+    return false;
+  }
+
   private boolean jj_3R_113() {
     if (jj_scan_token(LPAREN)) return true;
     return false;
   }
 
-  private boolean jj_3R_103() {
-    if (jj_scan_token(NOT)) return true;
+  private boolean jj_3R_102() {
     if (jj_scan_token(EXISTS)) return true;
+    if (jj_3R_114()) return true;
     return false;
   }
 
@@ -6070,29 +6042,23 @@ public class ARQParser extends ARQParser
     return false;
   }
 
-  private boolean jj_3R_102() {
-    if (jj_scan_token(EXISTS)) return true;
-    if (jj_3R_114()) return true;
-    return false;
-  }
-
   private boolean jj_3R_100() {
     if (jj_scan_token(REPLACE)) return true;
     if (jj_scan_token(LPAREN)) return true;
     return false;
   }
 
-  private boolean jj_3R_114() {
-    if (jj_scan_token(LBRACE)) return true;
-    return false;
-  }
-
   private boolean jj_3R_99() {
     if (jj_scan_token(SUBSTR)) return true;
     if (jj_scan_token(LPAREN)) return true;
     return false;
   }
 
+  private boolean jj_3R_114() {
+    if (jj_scan_token(LBRACE)) return true;
+    return false;
+  }
+
   private boolean jj_3_2() {
     if (jj_scan_token(DOT)) return true;
     if (jj_3R_36()) return true;
@@ -6245,6 +6211,51 @@ public class ARQParser extends ARQParser
     return false;
   }
 
+  private boolean jj_3R_79() {
+    if (jj_scan_token(VERSION)) return true;
+    if (jj_scan_token(NIL)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_78() {
+    if (jj_scan_token(SHA512)) return true;
+    if (jj_scan_token(LPAREN)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_149() {
+    if (jj_scan_token(STRING_LITERAL_LONG2)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_77() {
+    if (jj_scan_token(SHA384)) return true;
+    if (jj_scan_token(LPAREN)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_148() {
+    if (jj_scan_token(STRING_LITERAL_LONG1)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_76() {
+    if (jj_scan_token(SHA256)) return true;
+    if (jj_scan_token(LPAREN)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_147() {
+    if (jj_scan_token(STRING_LITERAL2)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_75() {
+    if (jj_scan_token(SHA1)) return true;
+    if (jj_scan_token(LPAREN)) return true;
+    return false;
+  }
+
   /** Generated Token Manager. */
   public ARQParserTokenManager token_source;
   JavaCharStream jj_input_stream;
@@ -6274,7 +6285,7 @@ public class ARQParser extends ARQParser
       jj_la1_init_6();
    }
    private static void jj_la1_init_0() {
-      jj_la1_0 = new int[] {0x7200000,0x180000,0x180000,0x0,0xc00000,0xc00000,0xe00,0x0,0x6e00,0x6e00,0x6e00,0x0,0x0,0x7e00,0x0,0x6e00,0x6e00,0x0,0x0,0x0,0xe00,0x0,0x0,0x0,0x20000000,0x18000000,0x6e00,0x0,0x6e00,0xe00,0x6e00,0x0,0x6e00,0x6e00,0x10000000,0x8000000,0x18000000,0x6000,0x0,0xe00,0x0,0x80000000,0xe00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe00,0x0,0x0,0x0,0xe00,0x0,0xe00,0xe00,0x0,0xe00,0x0,0x0,0x7e00,0x0,0x0,0x7e00,0x7e00,0x0,0x200000,0x7e00,0x0,0x0,0x7e00,0x7e00,0x0,0x0,0x0,0x0,0xe00,0x400000,0x0,0x0,0x0,0x0,0x7e00,0x0,0x7e00,0x0,0x46e00,0x46e00,0x0,0x46e00,0x7e00,0x46e00,0x0,0x46e00,0x46e00,0x46e00,0x0,0x0,0x0,0x0,0x40e00,0x0,0x0,0x0,0x0,0x40e00,0x0,0x40e00,0x40e00,0x40e00,0x40e00,0x0,0x7e00,0x7e00,0x7e00,0x6e00,0x6000,0x1e00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6e00,0x6e00,0x0,0x0,0x0,0x0,0x0,0x400000,0x6e00,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x0,0x0,0x0,0x0,0x0,0x8000,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0xe00,0
 xc00,0x1000,};
+      jj_la1_0 = new int[] {0x7200000,0x180000,0x180000,0x0,0xc00000,0xc00000,0xe00,0x0,0x6e00,0x6e00,0x6e00,0x0,0x0,0x7e00,0x0,0x6e00,0x6e00,0x0,0x0,0x0,0xe00,0x0,0x0,0x0,0x20000000,0x18000000,0x6e00,0x0,0x6e00,0xe00,0x6e00,0x0,0x6e00,0x6e00,0x10000000,0x8000000,0x18000000,0x6000,0x0,0xe00,0x0,0x80000000,0xe00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe00,0x0,0x0,0x0,0xe00,0x0,0xe00,0xe00,0x0,0xe00,0x0,0x0,0x7e00,0x0,0x0,0x7e00,0x7e00,0x0,0x200000,0x7e00,0x0,0x0,0x7e00,0x7e00,0x0,0x0,0x0,0x0,0xe00,0x400000,0x0,0x0,0x0,0x0,0x7e00,0x0,0x7e00,0x0,0x46e00,0x46e00,0x0,0x46e00,0x7e00,0x446e00,0x0,0x446e00,0x446e00,0x46e00,0x0,0x0,0x0,0x0,0x440e00,0x0,0x0,0x0,0x0,0x440e00,0x0,0x40e00,0x40e00,0x40e00,0x40e00,0x0,0x7e00,0x7e00,0x7e00,0x6e00,0x6000,0x1e00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6e00,0x6e00,0x0,0x0,0x0,0x0,0x0,0x400000,0x6e00,0x400000,0x400000,0x400000,0x400000,0x400000,0x400000,0x0,0x0,0x0,0x0,0x0,0x8000,0x8000,0x0,0x0,0x0,0x0,0x0,0x0,0x
 e00,0xc00,0x1000,};
    }
    private static void jj_la1_init_1() {
       jj_la1_1 = new int[] {0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x20000,0xb7c18000,0xb7c18000,0xb7c18000,0x10,0x10,0x0,0x30,0x0,0x0,0x10,0x20,0x10,0x8,0x20,0x40000,0x80000,0x0,0x0,0xb7c18000,0x20000,0xb7c18000,0xb7c18000,0xb7c18006,0x6,0xb7c18000,0xb7c18006,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10,0x10,0x8,0x80,0x80,0x88,0x88,0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x4001bd80,0x0,0x0,0x0,0x0,0x4001bd80,0x0,0x200,0xb7c18000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10000,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xb7c18000,0xb7c18000,0x0,0xb7c18000,0x0,0x0,0x0,0x0,0xb7c18000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x37c00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,};

Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/sparql_11/SPARQLParser11.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/sparql_11/SPARQLParser11.java?rev=1242901&r1=1242900&r2=1242901&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/sparql_11/SPARQLParser11.java (original)
+++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/lang/sparql_11/SPARQLParser11.java Fri Feb 10 19:53:38 2012
@@ -2852,7 +2852,7 @@ public class SPARQLParser11 extends SPAR
       jj_consume_token(-1);
       throw new ParseException();
     }
-      {if (true) return p ;}
+   {if (true) return p ;}
     throw new Error("Missing return statement in function");
   }
 

Added: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/P_Distinct.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/P_Distinct.java?rev=1242901&view=auto
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/P_Distinct.java (added)
+++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/P_Distinct.java Fri Feb 10 19:53:38 2012
@@ -0,0 +1,51 @@
+/*
+ * 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 com.hp.hpl.jena.sparql.path;
+
+import com.hp.hpl.jena.sparql.util.NodeIsomorphismMap ;
+
+/** A path element that, on evalution, returns only unique nodes for the path ends. */  
+public class P_Distinct extends P_Path1
+{
+    public P_Distinct(Path p)
+    {
+         super(p) ;
+    }
+    
+    @Override
+    public void visit(PathVisitor visitor)
+    { visitor.visit(this) ; }
+    
+    @Override
+    public boolean equalTo(Path path2, NodeIsomorphismMap isoMap)
+    {
+        if ( ! ( path2 instanceof P_Distinct ) ) return false ;
+        P_Distinct other = (P_Distinct)path2 ;
+        return getSubPath().equalTo(other.getSubPath(), isoMap)  ;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return getSubPath().hashCode() ^ hashDistinct ;
+    }
+
+   
+
+}

Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathBase.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathBase.java?rev=1242901&r1=1242900&r2=1242901&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathBase.java (original)
+++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathBase.java Fri Feb 10 19:53:38 2012
@@ -34,6 +34,8 @@ public abstract class PathBase implement
     protected static final int hashOneOrMore    = 0x198 ;
     protected static final int hashZeroOrOne    = 0x199 ;
     protected static final int hashFixedLength  = 0x200 ;
+    protected static final int hashDistinct     = 0x201 ;
+
     
     @Override
     public abstract int hashCode() ;

Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathEval.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathEval.java?rev=1242901&r1=1242900&r2=1242901&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathEval.java (original)
+++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathEval.java Fri Feb 10 19:53:38 2012
@@ -117,20 +117,22 @@ public class PathEval
     // ---- Worker ??
     static private void eval$(Graph graph, Node node, Path p, boolean forward, Collection<Node> acc)
     {
-        PathEvaluator evaluator = new PathEvaluator(graph, node, acc, forward) ;
+        PathEvaluatorN evaluator = new PathEvaluatorN(graph, node, acc, forward) ;
         p.visit(evaluator) ;
     }
     // ----
-    
-    private static class PathEvaluator implements PathVisitor
+    /** Path evaluator that produces duplicates.
+     *  This is the algorithm in the SPARQL 1.1 spec.  
+     * 
+     */
+    private static class PathEvaluatorN implements PathVisitor
     {
-
         private final Graph graph ;
         private final Node node ;
         private final Collection<Node> output ;
         private boolean forwardMode ; 
 
-        public PathEvaluator(Graph g, Node n, Collection<Node> output, boolean forward)
+        public PathEvaluatorN(Graph g, Node n, Collection<Node> output, boolean forward)
         {
             this.graph = g ; 
             this.node = n ;
@@ -309,8 +311,11 @@ public class PathEval
             // P_Mod(path, count, count)
             // One step.
             Iterator<Node> iter = eval(graph, node, pFixedLength.getSubPath(), forwardMode) ;
+            // Build a path for all remainign steps.
             long count2 = dec(pFixedLength.getCount()) ;
             P_FixedLength nextPath = new P_FixedLength(pFixedLength.getSubPath(), count2) ;
+            // For each element in the first step, do remaining step
+            // Accumulate across everything from first step.  
             for ( ; iter.hasNext() ; )
             {
                 Node n2 = iter.next() ;
@@ -320,6 +325,14 @@ public class PathEval
         }
 
         @Override
+        public void visit(P_Distinct pathDistinct)
+        {
+            // CRUDE - No optimization.
+            Iterator<Node> iter = eval(graph, node, pathDistinct.getSubPath(), forwardMode) ;
+            fill(Iter.distinct(iter)) ; 
+        }
+
+        @Override
         public void visit(P_ZeroOrOne path)
         { 
             doZero(path.getSubPath()) ;

Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathEval_ARQ.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathEval_ARQ.java?rev=1242901&r1=1242900&r2=1242901&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathEval_ARQ.java (original)
+++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathEval_ARQ.java Fri Feb 10 19:53:38 2012
@@ -270,6 +270,14 @@ public class PathEval_ARQ
         }
 
         @Override
+        public void visit(P_Distinct pathDistinct)
+        {
+            // CRUDE - No optimization.
+            Iterator<Node> iter = eval(graph, node, pathDistinct.getSubPath(), forwardMode) ;
+            fill(Iter.distinct(iter)) ; 
+        }
+
+        @Override
         public void visit(P_ZeroOrOne path)
         { 
             doZero(path.getSubPath()) ;

Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathFactory.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathFactory.java?rev=1242901&r1=1242900&r2=1242901&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathFactory.java (original)
+++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathFactory.java Fri Feb 10 19:53:38 2012
@@ -29,6 +29,7 @@ public class PathFactory
     public static Path pathInverse(Path path)           { return new P_Inverse(path) ; }
     public static Path pathMod(Path path, long min, long max)   { return new P_Mod(path, min, max) ; }
     public static Path pathFixedLength(Path path, long count)   { return new P_FixedLength(path, count) ; }
+    public static Path pathDistinct(Path path)          { return new P_Distinct(path) ; }
     
 
     public static Path pathAlt(Path path1, Path path2)  { return new P_Alt(path1, path2) ; }

Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathVisitor.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathVisitor.java?rev=1242901&r1=1242900&r2=1242901&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathVisitor.java (original)
+++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathVisitor.java Fri Feb 10 19:53:38 2012
@@ -28,6 +28,7 @@ public interface PathVisitor
     public void visit(P_Inverse inversePath) ;
     public void visit(P_Mod pathMod) ;
     public void visit(P_FixedLength pFixedLength) ;
+    public void visit(P_Distinct pathDistinct) ;
     public void visit(P_ZeroOrOne path) ;
     public void visit(P_ZeroOrMore path) ;
     public void visit(P_OneOrMore path) ;

Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathWriter.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathWriter.java?rev=1242901&r1=1242900&r2=1242901&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathWriter.java (original)
+++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/path/PathWriter.java Fri Feb 10 19:53:38 2012
@@ -242,6 +242,15 @@ public class PathWriter
         }
 
         @Override
+        public void visit(P_Distinct pathDistinct)
+        {
+            out.print("DISTINCT(") ;
+            pathDistinct.getSubPath().visit(this) ;
+            out.print(")") ;
+        }
+        
+
+        @Override
         public void visit(P_ZeroOrOne path)
         { printPathMod("?", path.getSubPath()) ; }
 

Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/sse/builders/BuilderPath.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/sse/builders/BuilderPath.java?rev=1242901&r1=1242900&r2=1242901&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/sse/builders/BuilderPath.java (original)
+++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/sse/builders/BuilderPath.java Fri Feb 10 19:53:38 2012
@@ -64,6 +64,7 @@ public class BuilderPath
         dispatch.put(Tags.tagPathMod, buildMod) ;
         
         dispatch.put(Tags.tagPathFixedLength, buildFixedLength) ;
+        dispatch.put(Tags.tagDistinct, buildDistinct) ;
         dispatch.put(Tags.tagPathZeroOrMore, buildZeroOrMore) ;
         dispatch.put(Tags.tagPathZeroOrOne, buildZeroOrOne) ;
         dispatch.put(Tags.tagPathOneOrMore, buildOneOrMore) ;
@@ -197,6 +198,17 @@ public class BuilderPath
         }
     } ;
 
+    final protected Build buildDistinct = new Build()
+    {
+        @Override
+        public Path make(ItemList list)
+        {
+            BuilderLib.checkLength(2, 2, list, "path distinct repeat: wanted 1 argument") ;
+            Path path  = build(list, 1) ;
+            return new P_Distinct(path) ;
+        }
+    } ;
+
     final protected Build buildZeroOrMore = new Build()
     {
         @Override

Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/sse/writers/WriterPath.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/sse/writers/WriterPath.java?rev=1242901&r1=1242900&r2=1242901&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/sse/writers/WriterPath.java (original)
+++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/sse/writers/WriterPath.java Fri Feb 10 19:53:38 2012
@@ -217,6 +217,15 @@ public class WriterPath
             writeOneLiner(path.getSubPath()) ;
             out.print(")") ;
         }
+        
+
+        @Override
+        public void visit(P_Distinct pathDistinct)
+        {
+            out.print("(distinct ") ;
+            output(pathDistinct.getSubPath()) ;
+            out.print(")") ;
+        }
 
         @Override
         public void visit(P_ZeroOrOne path)

Modified: incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/path/TestPath.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/path/TestPath.java?rev=1242901&r1=1242900&r2=1242901&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/path/TestPath.java (original)
+++ incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/path/TestPath.java Fri Feb 10 19:53:38 2012
@@ -21,13 +21,12 @@ package com.hp.hpl.jena.sparql.path;
 import static org.junit.Assert.assertEquals ;
 import static org.junit.Assert.fail ;
 
-import java.util.Arrays ;
-import java.util.HashSet ;
-import java.util.Iterator ;
-import java.util.Set ;
+import java.util.* ;
 
 import junit.framework.JUnit4TestAdapter ;
+import org.junit.Assert ;
 import org.junit.Test ;
+import org.openjena.atlas.iterator.Iter ;
 
 import com.hp.hpl.jena.graph.Graph ;
 import com.hp.hpl.jena.graph.Node ;
@@ -54,6 +53,7 @@ public class TestPath
 
     static Graph graph1 = GraphFactory.createDefaultGraph() ;
     static Graph graph2 = GraphFactory.createDefaultGraph() ;
+    static Graph graph3 = GraphFactory.createDefaultGraph() ;
     
     static Node n1 = Node.createURI("n1") ;
     static Node n2 = Node.createURI("n2") ;
@@ -77,6 +77,13 @@ public class TestPath
         graph2.add(new Triple(n1, p, n3)) ;
         graph2.add(new Triple(n2, q, n4)) ;
         graph2.add(new Triple(n3, q, n4)) ;
+        
+        // A DAG, one property
+        graph3.add(new Triple(n1, p, n2)) ;
+        graph3.add(new Triple(n1, p, n3)) ;
+        graph3.add(new Triple(n2, p, n4)) ;
+        graph3.add(new Triple(n3, p, n4)) ;
+
     }
     
     // ----
@@ -112,7 +119,7 @@ public class TestPath
     @Test public void parsePathErr_02()        { parse("()", false) ; }
     @Test public void parsePathErr_03()        { parse(":p :q", false) ; }
     
-    // Check we get the form on the right for the expression on the right.
+    // Check we get the form on the right for the expression on the left.
     @Test public void parseEquals_1()         {  parse("(:p)",        ":p") ; }
     @Test public void parseEquals_2()         {  parse(":p/:q/:r",    "(:p/:q)/:r") ; }
     @Test public void parseEquals_3()         {  parse("^:p^:q^:r",   "(^:p^:q)^:r") ; }
@@ -123,6 +130,12 @@ public class TestPath
     @Test public void parseEquals_8()         {  parse("!:q/:r",      "(!:q)/:r") ; }
     @Test public void parseEquals_9()         {  parse("!:q/:r",      "(!:q)/:r") ; }
 
+    @Test public void parsePathDistinct1()    {  parse("distinct(:p)", "distinct(:p)") ; }
+    @Test public void parsePathDistinct2()    {  parse("distinct(:p*)", "distinct(:p*)") ; }
+    @Test public void parsePathDistinct3()    {  parse("distinct((:p)*)", "distinct(:p*)") ; }
+    @Test public void parsePathDistinct4()    {  parse(":p/distinct(:p*)/:q", ":p/distinct(:p*)/:q") ; }
+    @Test public void parsePathDistinct5()    {  parse(":p/distinct(:p)*/:q", ":p/distinct(:p)*/:q") ; }
+
     // ----
     
     private void parse(String string) { parse(string, true) ; }
@@ -184,12 +197,19 @@ public class TestPath
     
 
     @Test public void path_20()   { test(graph2, n1,   ":p",          n2,n3) ; }
-    @Test public void path_21()   { test(graph2, n1,   ":p/:q",       n4) ; }
+    @Test public void path_21()   { test(graph2, n1,   ":p/:q",       n4, n4) ; }
     @Test public void path_22()   { test(graph2, n2,   "^:p|:q",      n1,n4) ; }
     @Test public void path_23()   { test(graph2, n2,   "^(:p|^:q)*",  n1,n2,n4) ; }
 
     @Test public void path_24()   { testReverse(graph1, n2,   ":p",          n1) ; }
     @Test public void path_25()   { testReverse(graph1, n3,   ":p/:p",       n1) ; }
+
+    @Test public void path_30()   { test(graph1, n1,   ":p*",       n1,n2,n3,n4) ; }
+    @Test public void path_31()   { test(graph2, n1,   ":p*",       n1,n2,n3) ; }
+    @Test public void path_32()   { test(graph3, n1,   ":p*",       n1,n2,n3,n4,n4) ; }
+    @Test public void path_33()   { test(graph3, n1,   "distinct(:p*)",       n1,n2,n3,n4) ; }
+    @Test public void path_34()   { test(graph3, n1,   "distinct(:p+)",       n2,n3,n4) ; }
+
     // ----
     private static void test(Graph graph, Node start, String string, Node... expectedNodes)
     {
@@ -206,11 +226,22 @@ public class TestPath
         Path p = PathParser.parse(string, pmap) ;
         Iterator<Node> resultsIter = 
             directionForward ? PathEval.eval(graph, start, p) : PathEval.evalInverse(graph, start, p) ; 
-        Set<Node> results = new HashSet<Node>() ;
-        for ( ; resultsIter.hasNext() ; )
-            results.add( resultsIter.next() ) ;
-
-        Set<Node> expected = new HashSet<Node>(Arrays.asList(expectedNodes)) ;
-        assertEquals(expected, results) ;
+        List<Node> results = Iter.toList(resultsIter) ;
+        List<Node> expected = Arrays.asList(expectedNodes) ;
+        // Unordered by counting equality.
+        Assert.assertTrue("expected:"+expected+", got:"+results, sameUnorder(expected, results)) ;
+    }
+    
+    private static boolean sameUnorder(List<Node> expected, List<Node> results)
+    {
+        // Copy - this is modified.
+        List<Node> x = new ArrayList<Node>(results) ;
+        for ( Node n : expected )
+        {
+            if ( ! x.contains(n) )
+                return false ;
+            x.remove(n) ;
+        }
+        return x.isEmpty() ;
     }
 }