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/03/30 19:49:18 UTC

svn commit: r1462840 - in /jena/trunk/jena-arq/src: main/java/org/apache/jena/riot/lang/ main/java/org/apache/jena/riot/out/ main/java/org/apache/jena/riot/system/ test/java/org/apache/jena/riot/lang/

Author: andy
Date: Sat Mar 30 18:49:17 2013
New Revision: 1462840

URL: http://svn.apache.org/r1462840
Log:
JENA-352 : Produce blank node ids based on large randon seed and the per-parser-run label.

Added:
    jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocator.java
    jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocatorHash.java
    jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocatorTraditional.java
    jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestBlankNodeAllocator.java
    jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLabelToNode.java
    jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestNodeToLabel.java
Modified:
    jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/LabelToNode.java
    jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/out/NodeToLabel.java
    jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/MapWithScope.java
    jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/RiotLib.java
    jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/SyntaxLabels.java
    jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TS_Lang.java

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocator.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocator.java?rev=1462840&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocator.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocator.java Sat Mar 30 18:49:17 2013
@@ -0,0 +1,40 @@
+/**
+ * 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.riot.lang;
+
+import com.hp.hpl.jena.graph.Node ;
+
+/** Interface to allocators for blank nodes. */
+public interface BlankNodeAllocator
+{
+    /** Allocate based on a non-null label.
+     * Calling this twice, with the same label will generate equivalent nodes
+     * but they may not be identicial (i.e they are .equals but may not be ==) 
+     */
+    public Node alloc(String label) ;
+    
+    /** Create a fresh blank node, different from anythign generated so far.
+     *  Will not clash with a node allocated by {@linkplain #alloc}
+     */
+    public Node create() ;
+    
+    /** Reset allocation state - calls to {@linkplain #alloc} or {@linkplain #create} */    
+    public void reset() ;
+}
+

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocatorHash.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocatorHash.java?rev=1462840&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocatorHash.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocatorHash.java Sat Mar 30 18:49:17 2013
@@ -0,0 +1,109 @@
+/**
+ * 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.riot.lang;
+
+import java.security.MessageDigest ;
+import java.security.NoSuchAlgorithmException ;
+import java.util.UUID ;
+
+import org.apache.jena.atlas.lib.Bytes ;
+import org.apache.jena.atlas.lib.Cache ;
+import org.apache.jena.atlas.lib.CacheFactory ;
+import org.apache.jena.atlas.lib.InternalErrorException ;
+import org.apache.jena.atlas.lib.cache.Getter ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.NodeFactory ;
+import com.hp.hpl.jena.rdf.model.AnonId ;
+
+/** Allocate bnode labels using a per-run seed and the label presented.
+ * <p>
+ * This is the most scalable, always legal allocator.
+ * <p>
+ * New allocators must be created per parser run, or .reset() called.
+ * These are fed to a digest to gve a bit string, (currently MD5, to get a 128bit bit string)
+ * that is used to form a bNode AnonId of hex digits.
+ * <p>  
+ * In addition there is a cache of label->node allocations,
+ * using the natural tendendency to locality in a database dump.
+ * (subject bNodes, bNodes in lists and other datavalues structures like
+ * unit values).
+ * <p>
+ * Not thread safe. 
+ */
+
+public class BlankNodeAllocatorHash implements BlankNodeAllocator
+{
+    private static String DigestAlgorithm = "MD5" ;
+    private static int CacheSize = 1000 ;
+    private MessageDigest mDigest ;
+    private byte[] seedBytes ;
+    private byte[] counterBytes = new byte[10] ;    // long+2 bytes to distinguish from UTF-8 bytes.   
+    private Cache<String, Node> cache ;
+    private long counter = 0 ;
+    
+    public BlankNodeAllocatorHash()
+    {
+        reset() ;
+        try { mDigest = MessageDigest.getInstance(DigestAlgorithm) ; }
+        catch (NoSuchAlgorithmException e) { throw new InternalErrorException("failed to create message digest", e) ; }
+        
+        Getter<String, Node> getter = new Getter<String, Node>() {
+            @Override public Node get(String key) { return alloc(key) ; }
+        } ;
+        Cache<String, Node> cache1 = CacheFactory.createCache(CacheSize) ;
+        cache = CacheFactory.createCacheWithGetter(cache1, getter) ;
+    }                                       
+
+    @Override
+    public void reset()
+    {
+        UUID seed = UUID.randomUUID() ;
+        seedBytes = new byte[128/8] ;
+        Bytes.setLong(seed.getMostSignificantBits(), seedBytes, 0) ;
+        Bytes.setLong(seed.getLeastSignificantBits(), seedBytes, 8) ;
+    }
+
+    @Override
+    public Node alloc(String label)
+    {
+        return alloc(Bytes.string2bytes(label)) ;
+    }
+    
+    
+    @Override
+    public Node create()
+    {
+        counter++ ;
+        // Make illegal string bytes so can't clash with alloc(String)
+        counterBytes[0] = 0 ;
+        counterBytes[1] = 0 ;
+        Bytes.setLong(counter, counterBytes, 2) ;
+        return alloc(counterBytes) ;
+    }
+
+    private Node alloc(byte[] labelBytes)
+    {
+        mDigest.update(seedBytes) ;
+        mDigest.update(labelBytes) ;
+        byte[] bytes = mDigest.digest() ;   // resets
+        String hexString = Bytes.asHexLC(bytes) ;
+        return NodeFactory.createAnon(new AnonId(hexString)) ;
+    }
+}

Added: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocatorTraditional.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocatorTraditional.java?rev=1462840&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocatorTraditional.java (added)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/BlankNodeAllocatorTraditional.java Sat Mar 30 18:49:17 2013
@@ -0,0 +1,59 @@
+/**
+ * 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.riot.lang;
+
+import java.util.HashMap ;
+import java.util.Map ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.NodeFactory ;
+
+/** Allocate blank ndoes according to the traditional policy (to jena 2.10.0)
+ *  This allocator has arbitrary sized state. 
+ *  Create a fresh one for each parser run.
+ */
+
+public class BlankNodeAllocatorTraditional implements BlankNodeAllocator
+{
+    Map<String, Node> map = new HashMap<String, Node>() ;
+    
+    public BlankNodeAllocatorTraditional()  {}
+
+    @Override
+    public void reset()         { map.clear() ; }
+
+    @Override
+    public Node alloc(String label)
+    {
+        Node b = map.get(label) ;
+        if ( b == null )
+        {
+            b = create() ;
+            map.put(label, b) ;
+        }
+        return b ;
+    }
+    
+    
+    @Override
+    public Node create()
+    {
+        return NodeFactory.createAnon() ;
+    }
+}

Modified: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/LabelToNode.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/LabelToNode.java?rev=1462840&r1=1462839&r2=1462840&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/LabelToNode.java (original)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/lang/LabelToNode.java Sat Mar 30 18:49:17 2013
@@ -21,6 +21,7 @@ import static java.lang.String.format ;
 
 import java.util.HashMap ;
 import java.util.Map ;
+import java.util.concurrent.atomic.AtomicLong ;
 
 import org.apache.jena.riot.SysRIOT ;
 import org.apache.jena.riot.out.NodeFmtLib ;
@@ -43,6 +44,9 @@ public class LabelToNode extends MapWith
     public static LabelToNode createScopeByDocument()
     { return new LabelToNode(new SingleScopePolicy(), nodeMaker) ; }
 
+    public static LabelToNode createScopeByDocumentHash()
+    { return new LabelToNode(new AllocScopePolicy(), new AllocNodeHash()) ; }
+    
     /** Allocation scoped by graph and label. */
     public static LabelToNode createScopeByGraph()
     { return new LabelToNode(new GraphScopePolicy(), nodeMaker) ; }
@@ -101,7 +105,9 @@ public class LabelToNode extends MapWith
             return x ;
         }
         @Override
-        public void clear() { map.clear(); }
+        public void clear() {
+            dftMap.clear() ;
+            map.clear(); }
     }
 
     /** No scope - use raw allocator */
@@ -114,62 +120,86 @@ public class LabelToNode extends MapWith
     }
 
     
-    // ======== Node Allocators 
+    // ======== Node Allocators
+    
+    // TODO Switch to BlankNodeAllocator and a singel wrapper.
+    // variables if the allocator is reusable across runs
+    // classes if a new one is needed each time.
+    // Shared ones must be thread-safe.
+    
+
+    /** Allocate bnode labels using a per-run see and the label presented.
+     *  This is the most scalable, always legal allocator.
+     *  Not thread safe - not reusable.
+     *  Create a new allocator for each parser run. 
+     */  
+    private static class AllocNodeHash implements Allocator<String, Node> {
+        private BlankNodeAllocator alloc = new BlankNodeAllocatorHash() ;
+        
+        @Override public Node alloc(String label)   { return alloc.alloc(label) ; }
+        @Override public Node create()              { return alloc.create() ; }
+        @Override public void reset()               { alloc.reset() ; }
+    } ;
     
     private static Allocator<String, Node> nodeMaker = new Allocator<String, Node>()
     {
-        @Override
-        public Node create(String label)
-        { return NodeFactory.createAnon() ; }
+        @Override public Node alloc(String label)       { return create() ;}
 
-        @Override
-        public void reset()     {}
+        @Override public Node create()                  { return NodeFactory.createAnon() ; }
+
+        @Override public void reset()                   {}
     } ;
 
     private static Allocator<String, Node> nodeMakerDeterministic = new Allocator<String, Node>()
     {
-        private long counter = 0 ;
+        private AtomicLong counter = new AtomicLong(0) ;
 
         @Override
-        public Node create(String label)
+        public Node alloc(String label)
+        {
+            return create() ;
+        }
+        
+        @Override public Node create()
         {
-            String $ = format("B0x%04X", ++counter) ;
+            String $ = format("B0x%04X", counter.incrementAndGet()) ;
             return NodeFactory.createAnon(new AnonId($)) ;
         }
 
+
         @Override
         public void reset()     {}
     } ;
     
     private static Allocator<String, Node> nodeMakerByLabel = new Allocator<String, Node>()
     {
-        private long counter = 0 ;
+        private AtomicLong counter = new AtomicLong(0) ;
         
         @Override
-        public Node create(String label)
+        public Node alloc(String label)
         {
-            if ( label == null )
-                label = SysRIOT.BNodeGenIdPrefix+counter++ ;
             return NodeFactory.createAnon(new AnonId(label)) ;
         }
 
+        @Override public Node create()      { return alloc(SysRIOT.BNodeGenIdPrefix+(counter.getAndIncrement())) ; } 
+        
         @Override
         public void reset()     {}
     } ;
     
     private static Allocator<String, Node> nodeMakerByLabelEncoded = new Allocator<String, Node>()
     {
-        private long counter = 0 ;
+        private AtomicLong counter = new AtomicLong(0) ;
         
         @Override
-        public Node create(String label)
+        public Node alloc(String label)
         {
-            if ( label == null )
-                label = SysRIOT.BNodeGenIdPrefix+counter++ ;
             return NodeFactory.createAnon(new AnonId(NodeFmtLib.decodeBNodeLabel(label))) ;
         }
 
+        @Override public Node create()      { return alloc(SysRIOT.BNodeGenIdPrefix+(counter.getAndIncrement())) ; }
         @Override
+        
         public void reset()     {}
     } ;
 }

Modified: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/out/NodeToLabel.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/out/NodeToLabel.java?rev=1462840&r1=1462839&r2=1462840&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/out/NodeToLabel.java (original)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/out/NodeToLabel.java Sat Mar 30 18:49:17 2013
@@ -21,6 +21,7 @@ package org.apache.jena.riot.out;
 import java.util.HashMap ;
 import java.util.Map ;
 
+import org.apache.jena.atlas.lib.InternalErrorException ;
 import org.apache.jena.riot.system.MapWithScope ;
 import org.apache.jena.riot.system.SyntaxLabels ;
 
@@ -56,7 +57,6 @@ public class NodeToLabel extends MapWith
 
     private static final NodeToLabel _internal = createBNodeByLabelEncoded() ;
     public static NodeToLabel labelByInternal() { return _internal ; }  
-    
 
     private NodeToLabel(ScopePolicy<Node, String, Node> scopePolicy, Allocator<Node, String> allocator)
     {
@@ -106,14 +106,21 @@ public class NodeToLabel extends MapWith
         private long counter = 0 ;
         
         @Override
-        public final String create(Node node)
+        public final String alloc(Node node)
         {
             if ( node.isURI() )         return labelForURI(node) ;
             if ( node.isLiteral() )     return labelForLiteral(node) ;
             if ( node.isBlank() )       return labelForBlank(node) ;
             if ( node.isVariable() )    return labelForVar(node) ;
-            
-            // Other??
+            throw new InternalErrorException("Node type not supported: "+node) ; 
+        }
+        
+        @Override
+        public final String create()    { return labelCreate() ; }
+
+        // Just return a fresh label.
+        protected String labelCreate()
+        {
             return Long.toString(counter++) ;
         }
 

Modified: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/MapWithScope.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/MapWithScope.java?rev=1462840&r1=1462839&r2=1462840&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/MapWithScope.java (original)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/MapWithScope.java Sat Mar 30 18:49:17 2013
@@ -27,15 +27,25 @@ public class MapWithScope<A, B, S>
 {
     // ======== Interfaces
     
-    protected interface ScopePolicy<A, B, S>
+    public interface ScopePolicy<A, B, S>
     {
         Map<A, B> getScope(S scope) ;
         void clear() ;
     }
-    
-    protected interface Allocator<A,B>
+
+    /** Allocate a B, given some A.
+     *  Only called once per instance of B if the ScopePolicy map is non-null.
+     */ 
+    public interface Allocator<A,B>
     {
-        public B create(A item) ;
+        /** Allocate - return the same B for a given A.
+         * "same" means .equals, not == 
+         */
+        public B alloc(A item) ;
+        
+        /** Create a fresh, unique (to within policy) B */  
+        public B create() ;
+        
         public void reset() ;
     }
     
@@ -59,19 +69,19 @@ public class MapWithScope<A, B, S>
         Map<A, B> map = scopePolicy.getScope(scope) ;
         if ( map == null )
             // No map - no item->allocation tracking.
-            return allocator.create(item) ;
+            return allocator.alloc(item) ;
 
         B mappedItem = map.get(item) ;
         if ( mappedItem == null )
         {
-            mappedItem = allocator.create(item) ;
+            mappedItem = allocator.alloc(item) ;
             map.put(item, mappedItem) ;
         }
         return mappedItem ;
     }
     
     /** Create a label that is guaranteed to be fresh */ 
-    public B create() { return allocator.create(null) ; }
+    public B create() { return allocator.create() ; }
     
     /** Clear scope and allocation */
     public void clear() { scopePolicy.clear() ; allocator.reset() ; }

Modified: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/RiotLib.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/RiotLib.java?rev=1462840&r1=1462839&r2=1462840&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/RiotLib.java (original)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/RiotLib.java Sat Mar 30 18:49:17 2013
@@ -133,7 +133,7 @@ public class RiotLib
     public static ParserProfile profile(String baseIRI, boolean resolveIRIs, boolean checking, ErrorHandler handler)
     {
         LabelToNode labelToNode = true
-            ? LabelToNode.createScopeByDocument() // SyntaxLabels.createNodeToLabel()
+            ? SyntaxLabels.createLabelToNode()
             : LabelToNode.createUseLabelEncoded() ;
         
         Prologue prologue ;

Modified: jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/SyntaxLabels.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/SyntaxLabels.java?rev=1462840&r1=1462839&r2=1462840&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/SyntaxLabels.java (original)
+++ jena/trunk/jena-arq/src/main/java/org/apache/jena/riot/system/SyntaxLabels.java Sat Mar 30 18:49:17 2013
@@ -21,10 +21,15 @@ package org.apache.jena.riot.system;
 import org.apache.jena.riot.lang.LabelToNode ;
 import org.apache.jena.riot.out.NodeToLabel ;
 
-/** Factory for default policies for syntax labels to and from nodes */  
+/** Factory for default policies for syntax labels to and from nodes
+ * For label to node (parsing) we use a scalable hashing scheme (MD5 of a seed and the label)
+ * 
+ * For node to label (pretty labels output), we use a unique tracking scheme. 
+ * Fully scalable writers use different polices and don't have short, pretty bNode labels.
+ */  
 public class SyntaxLabels
 {
     /** Default setup - scope by document, relabel BNodes ids to short forms */
     static public NodeToLabel createNodeToLabel() { return NodeToLabel.createScopeByDocument() ; }
-    static public LabelToNode createLabelToNode() { return LabelToNode.createScopeByDocument() ; }
+    static public LabelToNode createLabelToNode() { return LabelToNode.createScopeByDocumentHash() ; }
 }

Modified: jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TS_Lang.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TS_Lang.java?rev=1462840&r1=1462839&r2=1462840&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TS_Lang.java (original)
+++ jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TS_Lang.java Sat Mar 30 18:49:17 2013
@@ -28,7 +28,10 @@ import org.junit.runners.Suite ;
 @Suite.SuiteClasses( {
      TestIRI.class
     , TestLang.class
-    , TestNodeAllocator.class
+    , TestBlankNodeAllocator.class
+    , TestNodeAllocator.class       // Older tests 
+    , TestLabelToNode.class         // Newer tests
+    , TestNodeToLabel.class
     , TestTurtleTerms.class
     , TestLangNTriples.class
     , TestLangNQuads.class
@@ -37,6 +40,7 @@ import org.junit.runners.Suite ;
     , TestLangRdfJson.class
     , TestParserFactory.class
     , TestPipedRDFIterators.class
+    
 })
 
 

Added: jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestBlankNodeAllocator.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestBlankNodeAllocator.java?rev=1462840&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestBlankNodeAllocator.java (added)
+++ jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestBlankNodeAllocator.java Sat Mar 30 18:49:17 2013
@@ -0,0 +1,90 @@
+/**
+ * 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.riot.lang;
+
+import java.util.ArrayList ;
+import java.util.List ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.junit.Test ;
+import org.junit.runner.RunWith ;
+import org.junit.runners.Parameterized ;
+import org.junit.runners.Parameterized.Parameters ;
+
+import com.hp.hpl.jena.graph.Node ;
+
+@RunWith(Parameterized.class)
+public class TestBlankNodeAllocator extends BaseTest
+{
+    public interface Factory { public BlankNodeAllocator create() ; }
+    
+    @Parameters(name = "{index}: {0}")
+    public static Iterable<Object[]> data() {
+        List<Object[]> x = new ArrayList<Object[]>() ;
+        Factory fSeededHashAlloc = new Factory() {
+            @Override public BlankNodeAllocator create() { return new BlankNodeAllocatorHash() ; }
+            @Override public String toString() { return "SeededHash" ; }
+        } ;
+
+        Factory fUIDAlloc = new Factory() {
+            @Override public BlankNodeAllocator create() { return new BlankNodeAllocatorTraditional() ; }
+            @Override public String toString() { return "UID" ; }
+        } ;
+
+        x.add(new Object[]{fSeededHashAlloc}) ;
+        x.add(new Object[]{fUIDAlloc}) ;
+        return x ; 
+    }
+
+    private Factory factory ;
+    
+    public TestBlankNodeAllocator(Factory factory) { this.factory = factory ; }
+    
+    @Test public void alloc_01()
+    {
+        BlankNodeAllocator alloc = factory.create() ;
+        Node n = alloc.create() ;
+        assertTrue(n.isBlank()) ;
+    }
+    
+    @Test public void alloc_02()
+    {
+        BlankNodeAllocator alloc = factory.create() ;
+        Node n1 = alloc.create() ;
+        Node n2 = alloc.create() ;
+        assertNotEquals(n1, n2) ;
+    }
+    
+    @Test public void alloc_03()
+    {
+        BlankNodeAllocator alloc = factory.create() ;
+        Node n1 = alloc.alloc("foo") ;
+        Node n2 = alloc.alloc("foo") ;
+        assertEquals(n1, n2) ;
+    }
+    
+    @Test public void alloc_04()
+    {
+        BlankNodeAllocator alloc = factory.create() ;
+        Node n1 = alloc.alloc("foo") ;
+        Node n2 = alloc.alloc("bar") ;
+        assertNotEquals(n1, n2) ;
+    }
+}
+

Added: jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLabelToNode.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLabelToNode.java?rev=1462840&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLabelToNode.java (added)
+++ jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLabelToNode.java Sat Mar 30 18:49:17 2013
@@ -0,0 +1,232 @@
+/**
+ * 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.riot.lang;
+
+import java.util.ArrayList ;
+import java.util.List ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.riot.system.SyntaxLabels ;
+import org.junit.Test ;
+import org.junit.runner.RunWith ;
+import org.junit.runners.Parameterized ;
+import org.junit.runners.Parameterized.Parameters ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.NodeFactory ;
+
+@RunWith(Parameterized.class)
+public class TestLabelToNode extends BaseTest
+{
+    // See also TestNodeAlloc
+    
+    public interface LabelToNodeFactory { public LabelToNode create() ; }
+    
+    @Parameters(name = "{index}: {0}")
+    public static Iterable<Object[]> data() {
+        List<Object[]> x = new ArrayList<Object[]>() ;
+        LabelToNodeFactory fSyntaxLabels = new LabelToNodeFactory() {
+            @Override public LabelToNode create() { return SyntaxLabels.createLabelToNode() ; }
+            @Override public String toString() { return "SyntaxLabels.createLabelToNode" ; }
+        } ;
+
+        LabelToNodeFactory fScopeByDocument = new LabelToNodeFactory() {
+                @Override public LabelToNode create() { return LabelToNode.createScopeByDocument() ; }
+                @Override public String toString() { return "ScopeByDocument" ; }
+        } ;
+        LabelToNodeFactory fScopeByGraph = new LabelToNodeFactory() {
+            @Override public LabelToNode create() { return LabelToNode.createScopeByGraph() ; }
+            @Override public String toString() { return "ScopeByGraph" ; }
+        } ;
+        LabelToNodeFactory fUseLabelAsGiven = new LabelToNodeFactory() {
+            @Override public LabelToNode create() { return LabelToNode.createUseLabelAsGiven() ; }
+            @Override public String toString() { return "UseLabelAsGiven" ; }
+        } ;
+        LabelToNodeFactory fUseLabelEncoded = new LabelToNodeFactory() {
+            @Override public LabelToNode create() { return LabelToNode.createUseLabelEncoded() ; }
+            @Override public String toString() { return "UseLabelEncoded" ; }
+        } ;
+        LabelToNodeFactory fIncremental = new LabelToNodeFactory() {
+            @Override public LabelToNode create() { return LabelToNode.createIncremental() ; }
+            @Override public String toString() { return "Incremental" ; }
+        } ;
+
+        LabelToNodeFactory fScopeDocumentHash = new LabelToNodeFactory() {
+            @Override public LabelToNode create() { return LabelToNode.createScopeByDocumentHash() ; }
+            @Override public String toString() { return "ScopeByDocumentHash" ; }
+        } ;
+
+        // (1) Factory, whether DocScoped, (2) whether unique in a document (or graph) (3) whether unique per run 
+        x.add(new Object[]{fSyntaxLabels,       true, true}) ;
+        x.add(new Object[]{fScopeByDocument,    true, true}) ;
+        x.add(new Object[]{fScopeByGraph,       false, true}) ;
+        x.add(new Object[]{fUseLabelAsGiven,    true, false}) ;
+        x.add(new Object[]{fUseLabelEncoded,    true, false}) ;
+        x.add(new Object[]{fIncremental,        true, true}) ;
+        x.add(new Object[]{fScopeDocumentHash,  true, true}) ;
+        return x ; 
+    }
+
+    private LabelToNodeFactory factory ;
+    private Boolean unique ;
+    private Boolean docScope ;
+
+    public TestLabelToNode(LabelToNodeFactory factory, Boolean docScope, Boolean unique) 
+    {
+        this.factory = factory ;
+        this.docScope = docScope ;      // Does this LabelToNode obey the per-document uniqueness?
+        this.unique = unique ;          // Does this LabelToNode give uniqueness per initialization?
+    }
+    
+    @Test public void label2node_Create1()
+    {
+        LabelToNode mapper = factory.create() ;
+        Node n = mapper.create() ;
+        assertNotNull(n) ;
+    }
+    
+    @Test public void label2node_Create2()
+    {
+        LabelToNode mapper = factory.create() ;
+        Node n1 = mapper.create() ;
+        Node n2 = mapper.create() ;
+        assertNotNull(n1) ;
+        assertNotNull(n2) ;
+        assertNotEquals(n1, n2) ;
+    }
+
+    @Test public void label2node_Create3()
+    {
+        LabelToNode mapper1 = factory.create() ;
+        LabelToNode mapper2 = factory.create() ;
+        assertNotEquals(mapper1, mapper2) ;
+        Node n1 = mapper1.create() ;
+        Node n2 = mapper2.create() ;
+        assertNotNull(n1) ;
+        assertNotNull(n2) ;
+        assertNotEquals(n1, n2) ;
+    }
+    
+    @Test public void label2node_Label1()
+    {
+        LabelToNode mapper = factory.create() ;
+        Node n = mapper.get(null, "label") ;
+        assertNotNull(n) ;
+    }
+    
+    @Test public void label2node_Label2()
+    {
+        LabelToNode mapper = factory.create() ;
+        Node n1 = mapper.get(null, "label1") ;
+        Node n2 = mapper.get(null, "label2") ;
+        assertNotNull(n1) ;
+        assertNotNull(n2) ;
+        assertNotEquals(n1,n2) ;
+    }
+    
+    @Test public void label2node_Label3()
+    {
+        LabelToNode mapper = factory.create() ;
+        Node n1 = mapper.get(null, "label1") ;
+        Node n2 = mapper.get(null, "label1") ;
+        assertNotNull(n1) ;
+        assertNotNull(n2) ;
+        assertEquals(n1,n2) ;
+    }
+
+    @Test public void label2node_Label4()
+    {
+        Node g = NodeFactory.createURI("g") ;
+        LabelToNode mapper = factory.create() ;
+        Node n1 = mapper.get(g, "label1") ;
+        Node n2 = mapper.get(g, "label1") ;
+        assertNotNull(n1) ;
+        assertNotNull(n2) ;
+        assertEquals(n1,n2) ;
+    }
+
+    @Test public void label2node_Label5()
+    {
+        Node g1 = NodeFactory.createURI("g1") ;
+        Node g2 = NodeFactory.createURI("g2") ;
+        LabelToNode mapper = factory.create() ;
+        Node n1 = mapper.get(g1, "label1") ;
+        Node n2 = mapper.get(g2, "label1") ;
+        assertNotNull(n1) ;
+        assertNotNull(n2) ;
+        if ( docScope )
+            assertEquals(n1,n2) ;
+        else
+            assertNotEquals(n1,n2) ;
+    }
+
+    @Test public void label2node_Label6()
+    {
+        Node g = NodeFactory.createURI("g") ;
+        LabelToNode mapper = factory.create() ;
+        Node n1 = mapper.get(g, "label1") ;
+        Node n2 = mapper.get(null, "label1") ;
+        if ( docScope )
+            assertEquals(n1,n2) ;
+        else
+            assertNotEquals(n1,n2) ;
+    }
+
+    @Test public void label2node_Label7()
+    {
+        Node g1 = NodeFactory.createURI("g1") ;
+        Node g2 = NodeFactory.createURI("g1") ;
+        LabelToNode mapper = factory.create() ;
+        Node n1 = mapper.get(g1, "label1") ;
+        Node n2 = mapper.get(g2, "label2") ;
+        assertNotNull(n1) ;
+        assertNotNull(n2) ;
+        assertNotEquals(n1,n2) ;
+    }
+    
+    @Test public void label2node_Reset1()
+    {
+        LabelToNode mapper = factory.create() ;
+        Node n1 = mapper.get(null, "label1") ;
+        mapper.clear() ;
+        Node n2 = mapper.get(null, "label1") ;
+        assertNotNull(n1) ;
+        assertNotNull(n2) ;
+        if ( unique )
+            assertNotEquals(n1,n2) ;
+        else
+            assertEquals(n1,n2) ;
+    }
+
+    @Test public void label2node_Reset2()
+    {
+        LabelToNode mapper = factory.create() ;
+        Node g = NodeFactory.createURI("g") ;
+        Node n1 = mapper.get(g, "label1") ;
+        mapper.clear() ;
+        Node n2 = mapper.get(g, "label1") ;
+        assertNotNull(n1) ;
+        assertNotNull(n2) ;
+        if ( unique )
+            assertNotEquals(n1,n2) ;
+        else
+            assertEquals(n1,n2) ;
+    }
+}
+

Added: jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestNodeToLabel.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestNodeToLabel.java?rev=1462840&view=auto
==============================================================================
--- jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestNodeToLabel.java (added)
+++ jena/trunk/jena-arq/src/test/java/org/apache/jena/riot/lang/TestNodeToLabel.java Sat Mar 30 18:49:17 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 org.apache.jena.riot.lang;
+
+import java.util.ArrayList ;
+import java.util.List ;
+
+import org.apache.jena.atlas.junit.BaseTest ;
+import org.apache.jena.riot.out.NodeToLabel ;
+import org.apache.jena.riot.system.SyntaxLabels ;
+import org.junit.Test ;
+import org.junit.runner.RunWith ;
+import org.junit.runners.Parameterized ;
+import org.junit.runners.Parameterized.Parameters ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.NodeFactory ;
+
+@RunWith(Parameterized.class)
+public class TestNodeToLabel extends BaseTest
+{
+    public interface NodeToLabelFactory { public NodeToLabel create() ; }
+    
+    @Parameters(name = "{index}: {0}")
+    public static Iterable<Object[]> data() {
+        List<Object[]> x = new ArrayList<Object[]>() ;
+        
+        NodeToLabelFactory f0 = new NodeToLabelFactory() {
+            @Override public NodeToLabel create() { return SyntaxLabels.createNodeToLabel() ; }
+            @Override public String toString() { return "SyntaxLabels.createNodeToLabel" ; }
+        } ;
+        NodeToLabelFactory f1 = new NodeToLabelFactory() {
+            @Override public NodeToLabel create() { return NodeToLabel.createBNodeByIRI() ; }
+            @Override public String toString() { return "NodeToLabel.createBNodeByIRI()" ; }
+        } ;
+        NodeToLabelFactory f2 = new NodeToLabelFactory() {
+            @Override public NodeToLabel create() { return NodeToLabel.createBNodeByLabelAsGiven() ; }
+            @Override public String toString() { return "NodeToLabel.createBNodeByLabelAsGiven()" ; }
+        } ;
+        NodeToLabelFactory f3 = new NodeToLabelFactory() {
+            @Override public NodeToLabel create() { return NodeToLabel.createBNodeByLabelEncoded() ; }
+            @Override public String toString() { return "NodeToLabel.createBNodeByLabelEncoded()" ; }
+        } ;
+        NodeToLabelFactory f4 = new NodeToLabelFactory() {
+            @Override public NodeToLabel create() { return NodeToLabel.labelByInternal() ; }
+            @Override public String toString() { return "NodeToLabel.labelByInternal()" ; }
+        } ;
+
+        x.add(new Object[]{f0}) ;
+        x.add(new Object[]{f1}) ;
+        x.add(new Object[]{f2}) ;
+        x.add(new Object[]{f3}) ;
+        x.add(new Object[]{f4}) ;
+        return x ; 
+    }
+
+    private NodeToLabelFactory factory ;
+
+    public TestNodeToLabel(NodeToLabelFactory factory) 
+    {
+        this.factory = factory ;
+    }
+    
+    @Test public void node2label_01()
+    {
+        NodeToLabel mapper = factory.create() ;
+        String x1 = mapper.create() ;
+        String x2 = mapper.create() ;
+        assertNotNull(x1) ;
+        assertNotNull(x2) ;
+        assertNotEquals(x1, x2) ;
+    }
+
+    @Test public void node2label_02()
+    {
+        NodeToLabel mapper = factory.create() ;
+        Node x = NodeFactory.createAnon() ;
+        String s1 = mapper.get(null, x) ;
+        String s2 = mapper.get(null, x) ;
+        assertNotNull(s1) ;
+        assertNotNull(s2) ;
+        assertEquals(s1, s2) ;
+    }
+
+    @Test public void node2label_03()
+    {
+        NodeToLabel mapper = factory.create() ;
+        Node x1 = NodeFactory.createAnon() ;
+        Node x2 = NodeFactory.createAnon() ;
+        String s1 = mapper.get(null, x1) ;
+        String s2 = mapper.get(null, x2) ;
+        assertNotNull(s1) ;
+        assertNotNull(s2) ;
+        assertNotEquals(s1, s2) ;
+    }
+}
+