jena-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a...@apache.org
Subject [34/50] [abbrv] jena git commit: JENA-1396: Merge //github/afs/mantis as subdirectory jena-db/
Date Thu, 28 Sep 2017 11:08:50 GMT
http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/assembler/Vocab.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/assembler/Vocab.java
index 0000000,0000000..ae501bd
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/assembler/Vocab.java
@@@ -1,0 -1,0 +1,36 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.assembler ;
++
++import org.apache.jena.rdf.model.Property ;
++import org.apache.jena.rdf.model.Resource ;
++import org.apache.jena.rdf.model.ResourceFactory ;
++
++public class Vocab {
++    public static Resource type(String namespace, String localName) {
++        return ResourceFactory.createResource(namespace + localName) ;
++    }
++
++    public static Resource resource(String namespace, String localName) {
++        return ResourceFactory.createResource(namespace + localName) ;
++    }
++
++    public static Property property(String namespace, String localName) {
++        return ResourceFactory.createProperty(namespace + localName) ;
++    }
++}

http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/assembler/VocabTDB2.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/assembler/VocabTDB2.java
index 0000000,0000000..a661368
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/assembler/VocabTDB2.java
@@@ -1,0 -1,0 +1,90 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.assembler;
++
++
++import org.apache.jena.assembler.Assembler ;
++import org.apache.jena.assembler.ConstAssembler ;
++import org.apache.jena.assembler.JA ;
++import org.apache.jena.assembler.assemblers.AssemblerGroup ;
++import org.apache.jena.rdf.model.Property ;
++import org.apache.jena.rdf.model.Resource ;
++import org.apache.jena.sparql.core.assembler.AssemblerUtils ;
++import org.seaborne.tdb2.TDB2 ;
++
++public class VocabTDB2
++{
++    private static final String NS = TDB2.namespace ;
++    
++    public static String getURI() { return NS ; } 
++
++    // Types
++    public static final Resource tDatasetTDB        = Vocab.type(NS, "DatasetTDB2") ;
++    public static final Resource tDatasetTDB_alt    = Vocab.type(NS, "DatasetTDB") ;
++    public static final Resource tGraphTDB          = Vocab.type(NS, "GraphTDB2") ;
++    public static final Resource tGraphTDB_alt      = Vocab.type(NS, "GraphTDB") ;
++//    public static final Resource tTupleIndex        = Vocab.type(NS, "TupleIndex") ;
++    public static final Resource tNodeTable         = Vocab.type(NS, "NodeTable") ;
++
++    public static final Property pLocation          = Vocab.property(NS, "location") ;
++    public static final Property pUnionDefaultGraph = Vocab.property(NS, "unionDefaultGraph") ;
++    
++    public static final Property pIndex             = Vocab.property(NS, "index") ;
++    public static final Property pGraphName1        = Vocab.property(NS, "graphName") ;
++    public static final Property pGraphName2        = Vocab.property(NS, "namedGraph") ;
++    public static final Property pDataset           = Vocab.property(NS, "dataset") ;
++    
++    public static final Property pNodes             = Vocab.property(NS, "nodes") ;
++
++    // Indexes
++    public static final Property pDescription       = Vocab.property(getURI(), "description") ;
++    public static final Property pFile              = Vocab.property(getURI(), "file") ;
++
++    // Nodes
++    public static final Property pNodeIndex         = Vocab.property(getURI(), "nodeIndex") ;
++    public static final Property pNodeData          = Vocab.property(getURI(), "nodeData") ;
++    
++    // Setting
++    public static final Property pSetting           = Vocab.property(getURI(), "setting") ;
++    public static final Property pName              = Vocab.property(getURI(), "name") ;
++    public static final Property pValue             = Vocab.property(getURI(), "value") ;
++    
++    private static boolean initialized = false ; 
++    
++    static { init() ; }
++    
++    static synchronized public void init()
++    {
++        if ( initialized )
++            return ;
++        registerWith(Assembler.general) ;
++        initialized = true ;
++    }
++    
++    static void registerWith(AssemblerGroup g)
++    {
++        // Wire in the extension assemblers (extensions relative to the Jena assembler framework)
++        // Domain and range for properties.
++        // Separated and use ja:imports
++        AssemblerUtils.registerDataset(tDatasetTDB, new DatasetAssemblerTDB());
++        AssemblerUtils.registerDataset(tDatasetTDB_alt, new DatasetAssemblerTDB());
++        AssemblerUtils.register(ConstAssembler.general(), tGraphTDB, new TDBGraphAssembler(), JA.Model);
++        AssemblerUtils.register(ConstAssembler.general(), tGraphTDB_alt, new TDBGraphAssembler(), JA.Model);
++
++    }
++}

http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/graph/TransactionHandlerTDB.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/graph/TransactionHandlerTDB.java
index 0000000,0000000..664b005
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/graph/TransactionHandlerTDB.java
@@@ -1,0 -1,0 +1,60 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.graph;
++
++import org.apache.jena.graph.impl.TransactionHandlerBase ;
++import org.apache.jena.query.ReadWrite;
++import org.seaborne.dboe.transaction.txn.TransactionCoordinator;
++import org.seaborne.tdb2.store.DatasetGraphTDB;
++import org.seaborne.tdb2.store.GraphTDB ;
++
++public class TransactionHandlerTDB extends TransactionHandlerBase //implements TransactionHandler 
++{
++    private final GraphTDB graph ;
++    private final DatasetGraphTDB dsg;
++
++    public TransactionHandlerTDB(GraphTDB graph) {
++        this.graph = graph;
++        this.dsg = graph.getDSG();
++    }
++
++    @Override
++    public void abort() {
++        graph.getDSG().abort();
++        graph.getDSG().end();
++    }
++
++    @Override
++    public void begin() {
++        if ( TransactionCoordinator.promotion )
++            dsg.begin(ReadWrite.READ);
++        else
++            dsg.begin(ReadWrite.WRITE);
++    }
++
++    @Override
++    public void commit() {
++        dsg.commit();
++        dsg.end();
++    }
++
++    @Override
++    public boolean transactionsSupported() {
++        return true;
++    }
++}

http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/lib/Async.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/lib/Async.java
index 0000000,0000000..2a0bf52
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/lib/Async.java
@@@ -1,0 -1,0 +1,84 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.lib;
++
++import java.util.concurrent.* ;
++
++import org.seaborne.tdb2.TDBException ;
++
++/** Asyncrhonous operations support
++ *  This class provides a simple framework for asynchronous operations.
++ *  There is a thread pool and a pending queue. 
++ *  <p>
++ *  Default settings are thread pool of one and at most two pending operations.
++ *  When a new async operation is added, the pending queue is checked, and the
++ *  call blocks until the pending queue is below the threashold.
++ *  <p>
++ *  With the default setting of a thread pool of one, operations are
++ *  executed in the order submitted.
++ *  <p>
++ *  If the far end is the bottleneck, a longer queeue is no help.
++ */
++public final class Async {
++    // Currently specific to ThriftRunnable
++    private static final int THREAD_POOL_SIZE = 1 ;
++    private static final int PENDING_MAX = 2 ;
++    private static final int BlockingQueueSize = PENDING_MAX+2 ;
++    
++    private final int pendingQueueLimit ;
++    private final int blockingQueueSize ;
++    private final ExecutorService executorService; 
++    private final BlockingQueue<Future<Void>> outstanding ; 
++    
++    public Async() {
++        this(THREAD_POOL_SIZE, PENDING_MAX) ;
++    }
++
++    public Async(int threadPoolSize, int pendingQueueLimit) {
++        this.pendingQueueLimit = pendingQueueLimit ;
++        this.blockingQueueSize = this.pendingQueueLimit+1 ;
++        this.executorService = Executors.newFixedThreadPool(threadPoolSize) ;
++        this.outstanding = new ArrayBlockingQueue<>(BlockingQueueSize) ;
++    }
++    
++    /** Block until all pending oeprations has been completed */
++    public void completeAsyncOperations() {
++        reduceAsyncQueue(0) ;
++    }
++    
++    /** Block until the pending operations queue is below the given size. */
++    public void reduceAsyncQueue(int reduceSize) {
++        System.out.println("Reduce: "+outstanding.size()) ;
++        while ( outstanding.size() > reduceSize ) {
++            try { outstanding.take().get() ; }
++            catch (Exception ex) {
++                throw new TDBException("Exception taking from async queue", ex) ;
++            } 
++        }
++    }
++    
++    public void execAsync(Object lock, Runnable action) {
++        reduceAsyncQueue(pendingQueueLimit) ;
++        Future<Void> task = executorService.submit(()-> {
++            try { action.run() ; } 
++            catch (Exception ex)    { throw new TDBException("Unexpected exception: "+ex.getMessage(), ex) ; }
++            return null ;
++        }) ;
++        outstanding.add(task) ;
++    }
++}

http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/lib/NodeLib.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/lib/NodeLib.java
index 0000000,0000000..97951d6
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/lib/NodeLib.java
@@@ -1,0 -1,0 +1,141 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.lib;
++
++import static org.seaborne.tdb2.sys.SystemTDB.LenNodeHash;
++
++import java.security.DigestException;
++import java.security.MessageDigest;
++import java.security.NoSuchAlgorithmException;
++import java.util.Iterator;
++
++import org.apache.jena.atlas.iterator.Iter;
++import org.apache.jena.atlas.lib.Bytes;
++import org.apache.jena.atlas.lib.Pool;
++import org.apache.jena.atlas.lib.PoolBase;
++import org.apache.jena.atlas.lib.PoolSync;
++import org.apache.jena.atlas.logging.Log;
++import org.apache.jena.graph.Node;
++import org.apache.jena.sparql.util.NodeUtils;
++import org.seaborne.dboe.base.record.Record;
++import org.seaborne.tdb2.TDBException;
++import org.seaborne.tdb2.store.Hash;
++import org.seaborne.tdb2.store.NodeId;
++import org.seaborne.tdb2.store.NodeIdFactory;
++import org.seaborne.tdb2.store.nodetable.NodeTable;
++
++public class NodeLib {
++    public static Hash hash(Node n) {
++        Hash h = new Hash(LenNodeHash);
++        setHash(h, n);
++        return h;
++    }
++
++    private static String BNODE   = "bnode";
++    private static String URI     = "uri";
++    private static String LITERAL = "literal";
++
++    public static void setHash(Hash h, Node n) {
++        if ( n.isURI() )
++            hash(h, n.getURI(), null, null, URI);
++        else if ( n.isBlank() )
++            hash(h, n.getBlankNodeLabel(), null, null, BNODE);
++        else if ( n.isLiteral() ) {
++            String dt = n.getLiteralDatatypeURI();
++            if ( NodeUtils.isSimpleString(n) || NodeUtils.isLangString(n) ) {
++                // RDF 1.1 : No datatype for:
++                // xsd:String as simple literals
++                // rdf:langString and @
++                dt = null;
++            }
++            hash(h, n.getLiteralLexicalForm(), n.getLiteralLanguage(), dt, LITERAL);
++        } else
++            throw new TDBException("Attempt to hash something strange: " + n);
++    }
++
++    private static int                 InitialPoolSize = 5;
++    private static Pool<MessageDigest> digesters       = PoolSync.create(new PoolBase<MessageDigest>());
++    static {
++        try {
++            for ( int i = 0 ; i < InitialPoolSize ; i++ )
++                digesters.put(MessageDigest.getInstance("MD5"));
++        }
++        catch (NoSuchAlgorithmException e) {
++            Log.warn(NodeLib.class, "NoSuchAlgorithmException", e);
++            throw new RuntimeException(e);  
++        }
++    }
++
++    private static MessageDigest allocDigest() {
++        try {
++            MessageDigest disgest = digesters.get();
++            if ( disgest == null )
++                disgest = MessageDigest.getInstance("MD5");
++            return disgest;
++        }
++        catch (NoSuchAlgorithmException e) {
++            e.printStackTrace();
++            return null;
++        }
++    }
++
++    private static void deallocDigest(MessageDigest digest) {
++        digest.reset();
++        digesters.put(digest);
++    }
++
++    private static void hash(Hash h, String lex, String lang, String datatype, String nodeName) {
++        if ( datatype == null )
++            datatype = "";
++        if ( lang == null )
++            lang = "";
++        String toHash = lex + "|" + lang + "|" + datatype + "|" + nodeName;
++        MessageDigest digest;
++        try {
++            // MessageDigest.getInstance("MD5");
++            digest = allocDigest();
++            digest.update(Bytes.string2bytes(toHash));
++            if ( h.getLen() == 16 ) {
++                // MD5 is 16 bytes.
++                digest.digest(h.getBytes(), 0, 16);
++            } else {
++                byte b[] = digest.digest(); // 16 bytes.
++                System.arraycopy(b, 0, h.getBytes(), 0, h.getLen());
++            }
++            deallocDigest(digest);
++            return;
++        }
++        catch (DigestException ex) {
++            Log.error(NodeLib.class, "DigestException", ex);
++        }
++    }
++
++    public static NodeId getNodeId(Record r, int idx) {
++        return NodeIdFactory.get(r.getKey(), idx);
++    }
++
++    public static Node termOrAny(Node node) {
++        if ( node == null || node.isVariable() )
++            return Node.ANY;
++        return node;
++    }
++
++    public static Iterator<Node> nodes(final NodeTable nodeTable, Iterator<NodeId> iter) {
++        return Iter.map(iter, nodeTable::getNodeForNodeId);
++    }
++}

http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/lib/TupleLib.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/lib/TupleLib.java
index 0000000,0000000..7f554f9
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/lib/TupleLib.java
@@@ -1,0 -1,0 +1,154 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.lib;
++
++import java.util.Iterator ;
++
++import org.apache.jena.atlas.iterator.Iter ;
++import org.apache.jena.atlas.lib.InternalErrorException ;
++import org.apache.jena.atlas.lib.tuple.Tuple ;
++import org.apache.jena.atlas.lib.tuple.TupleFactory ;
++import org.apache.jena.atlas.lib.tuple.TupleMap ;
++import org.apache.jena.graph.Node ;
++import org.apache.jena.graph.Triple ;
++import org.apache.jena.sparql.core.Quad ;
++import org.seaborne.dboe.base.record.Record ;
++import org.seaborne.dboe.base.record.RecordFactory ;
++import org.seaborne.tdb2.TDBException ;
++import org.seaborne.tdb2.store.NodeId ;
++import org.seaborne.tdb2.store.NodeIdFactory;
++import org.seaborne.tdb2.store.nodetable.NodeTable ;
++
++public class TupleLib
++{
++    public static Iterator<Tuple<Node>> convertToNodes(final NodeTable nodeTable, Iterator<Tuple<NodeId>> iter) {
++        return Iter.map(iter, item -> tupleNodes(nodeTable, item));
++    }
++
++    public static Iterator<Tuple<NodeId>> convertToNodeId(final NodeTable nodeTable, Iterator<Tuple<Node>> iter) {
++        return Iter.map(iter, item -> tupleNodeIds(nodeTable, item));
++    }
++
++    // Leave - bypasses extract step in Tuple<NodeId> -> Tuple<Node> -> Triple
++    public static Iterator<Triple> convertToTriples(final NodeTable nodeTable, Iterator<Tuple<NodeId>> iter) {
++        return Iter.map(iter, item -> triple(nodeTable, item));
++    }
++
++    public static Iterator<Quad> convertToQuads(final NodeTable nodeTable, Iterator<Tuple<NodeId>> iter) {
++        return Iter.map(iter, item -> quad(nodeTable, item));
++    }
++
++    public static Tuple<Node> tupleNodes(NodeTable nodeTable, Tuple<NodeId> ids) {
++        int N = ids.len();
++        Node[] n = new Node[N];
++        for ( int i = 0 ; i < N ; i++ )
++            n[i] = nodeTable.getNodeForNodeId(ids.get(i));
++        return TupleFactory.create(n);
++    }
++
++    public static Tuple<NodeId> tupleNodeIds(NodeTable nodeTable, Tuple<Node> nodes) {
++        int N = nodes.len();
++        NodeId[] n = new NodeId[N];
++        for ( int i = 0 ; i < N ; i++ )
++            n[i] = nodeTable.getNodeIdForNode(nodes.get(i));
++        return TupleFactory.create(n);
++    }
++    
++    private static Triple triple(NodeTable nodeTable, Tuple<NodeId> tuple) {
++        if ( tuple.len() != 3 )
++            throw new TDBException("Tuple is not of length 3: " + tuple);
++        return triple(nodeTable, tuple.get(0), tuple.get(1), tuple.get(2));
++    }
++
++    private static Triple triple(NodeTable nodeTable, NodeId s, NodeId p, NodeId o) {
++        if ( ! NodeId.isConcrete(s) )
++            throw new InternalErrorException("Invalid id for subject: "+fmt(s,p,o)) ;
++        if ( ! NodeId.isConcrete(p) )
++            throw new InternalErrorException("Invalid id for predicate: "+fmt(s,p,o)) ;
++        if ( ! NodeId.isConcrete(o) )
++            throw new InternalErrorException("Invalid id for object: "+fmt(s,p,o)) ;
++        
++        Node sNode = nodeTable.getNodeForNodeId(s) ;
++        if ( sNode == null )
++            throw new InternalErrorException("Invalid id node for subject (null node): "+fmt(s,p,o)) ;
++
++        Node pNode = nodeTable.getNodeForNodeId(p) ;
++        if ( pNode == null )
++        {
++            nodeTable.getNodeForNodeId(p) ;
++            throw new InternalErrorException("Invalid id node for predicate (null node): "+fmt(s,p,o)) ;
++        }
++        
++        Node oNode = nodeTable.getNodeForNodeId(o) ;
++        if ( oNode == null )
++            throw new InternalErrorException("Invalid id node for object (null node): "+fmt(s,p,o)) ;
++        
++        return new Triple(sNode, pNode, oNode) ;
++    }
++    
++    private static String fmt(NodeId s, NodeId p, NodeId o)
++    {
++        return "("+s+", "+p+", "+o+")" ;
++    }
++    
++    private static Quad quad(NodeTable nodeTable, Tuple<NodeId> tuple) 
++    {
++        if ( tuple.len() != 4 )
++            throw new TDBException("Tuple is not of length 4: "+tuple) ;
++        return quad(nodeTable, tuple.get(0), tuple.get(1), tuple.get(2), tuple.get(3)) ;
++    }
++    
++    private static Quad quad(NodeTable nodeTable, NodeId g, NodeId s, NodeId p, NodeId o) 
++    {
++        Node gNode = nodeTable.getNodeForNodeId(g) ;
++        Node sNode = nodeTable.getNodeForNodeId(s) ;
++        Node pNode = nodeTable.getNodeForNodeId(p) ;
++        Node oNode = nodeTable.getNodeForNodeId(o) ;
++        return new Quad(gNode, sNode, pNode, oNode) ;
++    }
++
++    // ---- Tuples and Records
++    public static Tuple<NodeId> tuple(Record r, TupleMap tMap) {
++        // Unmapping.
++        int N = r.getKey().length/NodeId.SIZE;
++        NodeId[] nodeIds = new NodeId[N] ;
++        for ( int i = 0 ; i < N ; i++ )
++        {
++            int j = i ;
++            if ( tMap != null )
++                j = tMap.unmapIdx(i) ;
++            NodeId id = NodeIdFactory.get(r.getKey(), j*NodeId.SIZE) ;
++            nodeIds[i] = id ;
++        }
++        return TupleFactory.create(nodeIds) ;
++    }
++
++
++    public static Record record(RecordFactory factory, Tuple<NodeId> tuple, TupleMap tMap) {
++        // Mapping.
++        byte[] b = new byte[tuple.len()*NodeId.SIZE] ;
++        for ( int i = 0 ; i < tuple.len() ; i++ )
++        {
++            int j = tMap.getSlotIdx(i) ;
++            // i'th Nodeid goes to j'th bytes slot.
++            NodeIdFactory.set(tuple.get(j), b, i*NodeId.SIZE) ;
++        }
++            
++        return factory.create(b) ;
++    }
++}

http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/loader/Loader.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/loader/Loader.java
index 0000000,0000000..8555088f
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/loader/Loader.java
@@@ -1,0 -1,0 +1,78 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.loader;
++
++import org.apache.jena.atlas.lib.ProgressMonitor ;
++import org.apache.jena.atlas.logging.FmtLog ;
++import org.apache.jena.query.Dataset ;
++import org.apache.jena.riot.RDFDataMgr ;
++import org.apache.jena.riot.system.ProgressStreamRDF ;
++import org.apache.jena.riot.system.StreamRDF ;
++import org.apache.jena.riot.system.StreamRDFLib ;
++import org.seaborne.dboe.jenax.Txn ;
++import org.seaborne.tdb2.store.DatasetGraphTDB ;
++import org.slf4j.Logger ;
++import org.slf4j.LoggerFactory ;
++
++public class Loader {
++    
++    private static final int BATCH_SIZE = 100 ;
++    
++    // XXX StreamRDFBatchSplit and parallel index update.
++    private static Logger LOG = LoggerFactory.getLogger("Loader") ;
++    
++    public static void bulkLoad(Dataset ds, String ... files) {
++        DatasetGraphTDB dsg = (DatasetGraphTDB)ds.asDatasetGraph() ;
++        StreamRDF s1 = StreamRDFLib.dataset(dsg) ;
++        ProgressMonitor plog = ProgressMonitor.create(LOG, "Triples", 100000, 10) ;
++        ProgressStreamRDF sMonitor = new ProgressStreamRDF(s1, plog) ;
++        StreamRDF s3 = sMonitor ;
++
++        plog.start(); 
++        Txn.executeWrite(ds, () -> {
++            for ( String fn : files ) {
++                if ( files.length > 1 )
++                    FmtLog.info(LOG, "File: %s",fn);
++                RDFDataMgr.parse(s3, fn) ;
++            }
++        }) ;
++        plog.finish();
++        plog.finishMessage();
++    }
++    
++    public static void bulkLoadBatching(Dataset ds, String ... files) {
++        DatasetGraphTDB dsg = (DatasetGraphTDB)ds.asDatasetGraph() ;
++
++        StreamRDFBatchSplit s1 = new StreamRDFBatchSplit(dsg, 10) ;
++        ProgressMonitor plog = ProgressMonitor.create(LOG, "Triples", 100000, BATCH_SIZE) ;
++        // Want the monitor on the outside to capture transaction wrapper costs.
++        StreamRDF s3 = new ProgressStreamRDF(s1, plog) ;
++
++        plog.start(); 
++        Txn.executeWrite(ds, () -> {
++            for ( String fn : files ) {
++                if ( files.length > 1 )
++                    FmtLog.info(LOG, "File: %s",fn);
++                RDFDataMgr.parse(s3, fn) ;
++            }
++        }) ;
++        plog.finish();  
++        plog.finishMessage();
++    }
++}
++

http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/loader/StreamRDFBatchSplit.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/loader/StreamRDFBatchSplit.java
index 0000000,0000000..fb7e25c
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/loader/StreamRDFBatchSplit.java
@@@ -1,0 -1,0 +1,224 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.loader;
++
++import java.util.* ;
++import java.util.stream.Collectors ;
++
++import org.apache.jena.atlas.lib.tuple.Tuple ;
++import org.apache.jena.atlas.lib.tuple.TupleFactory ;
++import org.apache.jena.graph.Node ;
++import org.apache.jena.graph.Triple ;
++import org.apache.jena.riot.other.BatchedStreamRDF ;
++import org.apache.jena.riot.system.StreamRDF ;
++import org.apache.jena.sparql.core.Quad ;
++import org.seaborne.dboe.transaction.txn.Transaction ;
++import org.seaborne.tdb2.TDBException ;
++import org.seaborne.tdb2.setup.TDBDatasetDetails ;
++import org.seaborne.tdb2.store.DatasetGraphTDB ;
++import org.seaborne.tdb2.store.NodeId ;
++import org.seaborne.tdb2.store.NodeIdFactory;
++import org.seaborne.tdb2.store.nodetable.NodeTable ;
++import org.seaborne.tdb2.store.tupletable.TupleTable ;
++import org.slf4j.Logger ;
++import org.slf4j.LoggerFactory ;
++
++/**
++ * @see BatchedStreamRDF BatchedStreamRDF, which batches by subject
++ */
++public class StreamRDFBatchSplit implements StreamRDF {
++    // Need to handle transactions?
++    // Lizard des (TxnClient) 
++    
++    private static Logger log = LoggerFactory.getLogger(StreamRDFBatchSplit.class) ;
++    protected static NodeId placeholder = NodeIdFactory.genUnique();
++    protected final List<Triple> triples ;
++    protected final List<Tuple<NodeId>> tuples ;
++    protected final Map<Node, NodeId> mapping ;
++    
++    private final int batchSize ;
++    private final TDBDatasetDetails details ;
++    private final DatasetGraphTDB dsg ;
++    private Transaction txn = null ;
++    
++    public StreamRDFBatchSplit(DatasetGraphTDB dsg, int batchSize) {
++        this.dsg = dsg ;
++        this.batchSize = batchSize ;
++        this.triples = new ArrayList<>(batchSize) ;
++        this.tuples = new ArrayList<>(triples.size()) ;
++        this.mapping = new HashMap<>(2*batchSize) ;
++        this.details = new TDBDatasetDetails(dsg) ;
++    }
++        
++    @Override
++    public void start() {
++        log.info("Batch size: "+batchSize);
++        // Multiple starts in one trnasaciton are possible.
++        if ( txn == null )
++            txn = dsg.getTxnSystem().getThreadTransaction() ;
++        if ( txn == null )
++            throw new TDBException("Not in a transaction") ;
++    }
++
++    @Override
++    public void triple(Triple triple) {
++        //Find nodes.
++        //log.info("Triple: "+triple) ;
++        processNode(triple.getSubject()) ;
++        processNode(triple.getPredicate()) ;
++        processNode(triple.getObject()) ;
++        triples.add(triple) ;
++        if ( triples.size() >= batchSize )
++            processBatch() ;
++    }
++
++    int batchNumber = 0 ;
++    
++    protected void processBatch() {
++        //if ( batchNumber < 10 )
++        batchNumber++ ;
++        //FmtLog.info(log, ">>processBatch: [%d]->%d", batchNumber, triples.size()) ;
++
++        Set<Node> requiredNodes = mapping.keySet() ;
++
++        boolean executeBatchNodesPhase = true ;
++        boolean executeIndexPhase = true ;
++        // Derived control.
++        boolean batchUpdateIndexes = true ;
++        
++        if ( executeBatchNodesPhase )
++            // Check this is a cache node table.
++            batchUpdateNodes(requiredNodes, details) ;
++        
++        if ( executeIndexPhase ) {
++            if ( batchUpdateIndexes )
++                batchUpdateIndexes(dsg, details, triples, /*tuples*/null) ;
++            else
++                incrementalUpdateIndexes(triples, dsg) ;
++        }
++        triples.clear();
++        tuples.clear() ;
++        //FmtLog.info(log, "<<processBatch") ;
++        mapping.clear();
++//        if ( batchSize < 10 )
++//            System.exit(0) ;
++    }
++   
++    private static void incrementalUpdateIndexes(List<Triple> triples, DatasetGraphTDB dsg) {
++        for ( Triple triple : triples ) {
++            dsg.getTripleTable().add(triple); 
++        }
++    }
++
++    /** This files the cache so that the tuples adds are faster */ 
++    private static void batchUpdateNodes(Set<Node> required, TDBDatasetDetails details) {
++        List<Node> nodes = new ArrayList<>() ;
++        // Resolve NodeIds
++        
++        // ** Move this into cache - code. 
++        
++        for ( Node n : required ) {
++            // 
++            if ( details.ntCache.getNodeIdForNodeCache(n) == null /* set input - no need :: && ! nodes.contains(n) /* Not good?*/ )
++                nodes.add(n) ;
++        }
++        //log.info("Batch nodes: "+nodes.size()) ;
++        // This drops into the default method.
++        details.ntTop.bulkNodeToNodeId(nodes, true) ;
++        
++        // Check
++        // Resolve NodeIds
++        for ( Node n : required ) {
++            if ( details.ntCache.getNodeIdForNodeCache(n) == null  )
++                log.info("Not in cache: "+n) ;
++        }
++        //details.ntCluster.bulkNodeToNodeId(nodes, true) ;
++        
++        
++        
++    }
++
++    private static void batchUpdateIndexes(DatasetGraphTDB dsg, TDBDatasetDetails details, List<Triple> batchTriples, List<Tuple<NodeId>> workspace) {
++        List<Tuple<NodeId>> tuples = workspace ;
++        if ( tuples == null )
++            tuples = new ArrayList<>(batchTriples.size()) ;
++
++        convert(batchTriples, tuples, details.ntTop) ;
++        //log.info("Batch triples: "+tuples.size()) ;
++
++        TupleTable tupleTable = dsg.getTripleTable().getNodeTupleTable().getTupleTable() ;
++        tupleTable.addAll(tuples);
++    }
++
++    // check for duplicate code
++    private static List<Tuple<NodeId>> convert(List<Triple> triples, NodeTable nodeTable) {
++        return triples.stream().map(t -> TupleFactory.tuple(nodeTable.getAllocateNodeId(t.getSubject()),
++                                                            nodeTable.getAllocateNodeId(t.getPredicate()),
++                                                            nodeTable.getAllocateNodeId(t.getObject())))
++            .collect(Collectors.toList());
++    }
++    
++    private static void convert(List<Triple> triples, List<Tuple<NodeId>> tuples, NodeTable nodeTable) {
++        // Slightly faster.  But larger batches?
++        for ( Triple t : triples ) {
++            NodeId nid_s = nodeTable.getAllocateNodeId(t.getSubject()) ;
++            NodeId nid_p = nodeTable.getAllocateNodeId(t.getPredicate()) ;
++            NodeId nid_o = nodeTable.getAllocateNodeId(t.getObject()) ;
++            Tuple<NodeId> x = TupleFactory.tuple(nid_s, nid_p, nid_o) ;
++            tuples.add(x) ;
++        }
++        
++//        triples.stream().map(t->
++//                  TupleFactory.tuple
++//                  (nodeTable.getAllocateNodeId(t.getSubject()),
++//                   nodeTable.getAllocateNodeId(t.getPredicate()),
++//                   nodeTable.getAllocateNodeId(t.getObject())))
++//                .collect(Collectors.toCollection(()->tuples)) ;
++    }
++    
++    
++    private void processNode(Node node) {
++        
++        if ( mapping.containsKey(node)) 
++            return ;
++        
++        if ( NodeId.hasInlineDatatype(node) ) {
++            NodeId nodeId = NodeId.inline(node) ;
++            if ( nodeId != null )
++                return ;
++        }
++        mapping.put(node, placeholder) ;
++    }
++    
++    @Override
++    public void quad(Quad quad) {}
++
++    @Override
++    public void base(String base) {}
++
++    @Override
++    public void prefix(String prefix, String iri) {}
++
++    @Override
++    public void finish() { 
++        if ( ! triples.isEmpty() )
++            processBatch() ;
++    }
++
++}
++

http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/migrate/A2.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/migrate/A2.java
index 0000000,0000000..4dd1a90
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/migrate/A2.java
@@@ -1,0 -1,0 +1,37 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.migrate;
++
++import org.apache.jena.sparql.algebra.Op ;
++import org.apache.jena.sparql.algebra.Transform ;
++import org.apache.jena.sparql.algebra.Transformer ;
++import org.apache.jena.sparql.core.Quad ;
++
++public class A2
++{
++    /** Convert a pattern, assumed to be quad form, 
++     * so that the default graph is the union of named graphs.  
++     */
++    public static Op unionDefaultGraphQuads(Op op)
++    {
++        // Rewrite so that any explicitly named "default graph" is union graph.
++        Transform t = new TransformGraphRename(Quad.defaultGraphNodeGenerated, Quad.unionGraph)  ;
++        op = Transformer.transform(t, op) ;
++        return op ;
++    }
++}

http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/migrate/TransformGraphRename.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/migrate/TransformGraphRename.java
index 0000000,0000000..4759bed
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/migrate/TransformGraphRename.java
@@@ -1,0 -1,0 +1,53 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.migrate;
++
++import org.apache.jena.graph.Node ;
++import org.apache.jena.sparql.algebra.Op ;
++import org.apache.jena.sparql.algebra.TransformCopy ;
++import org.apache.jena.sparql.algebra.op.OpGraph ;
++import org.apache.jena.sparql.algebra.op.OpQuadPattern ;
++
++public class TransformGraphRename extends TransformCopy
++{ 
++    private Node oldGraphName ;
++    private Node newGraphName ;
++
++    public TransformGraphRename(Node oldGraphName, Node newGraphName)
++    {
++        this.oldGraphName = oldGraphName ;
++        this.newGraphName = newGraphName ;
++    }
++
++    // Does not affect variables.
++    @Override
++    public Op transform(OpGraph opGraph, Op x)
++    { 
++        if ( opGraph.getNode().equals(oldGraphName) )
++            opGraph = new OpGraph(newGraphName, x) ;
++        return super.transform(opGraph, x) ;
++    }
++
++    @Override
++    public Op transform(OpQuadPattern opQuadPattern)
++    {
++        if ( opQuadPattern.getGraphNode().equals(oldGraphName) )
++            opQuadPattern = new OpQuadPattern(newGraphName, opQuadPattern.getBasicPattern()) ;
++        return super.transform(opQuadPattern) ;
++    }
++}

http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/modify/UpdateEngineTDB.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/modify/UpdateEngineTDB.java
index 0000000,0000000..844f5a9
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/modify/UpdateEngineTDB.java
@@@ -1,0 -1,0 +1,52 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.modify;
++
++import org.apache.jena.sparql.core.DatasetGraph ;
++import org.apache.jena.sparql.engine.binding.Binding ;
++import org.apache.jena.sparql.modify.UpdateEngine ;
++import org.apache.jena.sparql.modify.UpdateEngineFactory ;
++import org.apache.jena.sparql.modify.UpdateEngineMain ;
++import org.apache.jena.sparql.modify.UpdateEngineRegistry ;
++import org.apache.jena.sparql.util.Context ;
++import org.seaborne.tdb2.store.DatasetGraphTxn ;
++
++public class UpdateEngineTDB extends UpdateEngineMain
++{
++    public UpdateEngineTDB(DatasetGraphTxn graphStore, Binding inputBinding, Context context)
++    { super(graphStore, inputBinding, context) ; }
++    
++
++    // ---- Factory
++    public static UpdateEngineFactory getFactory() { 
++        return new UpdateEngineFactory()
++        {
++            @Override
++            public boolean accept(DatasetGraph dataset, Context context) {
++                return (dataset instanceof DatasetGraphTxn) ;
++            }
++            
++            @Override
++            public UpdateEngine create(DatasetGraph dataset, Binding inputBinding, Context context) {
++                return new UpdateEngineTDB((DatasetGraphTxn)dataset, inputBinding, context);
++            }
++        } ;
++    }
++
++    public static void register() { UpdateEngineRegistry.get().add(getFactory()) ; }
++}

http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/setup/ComponentIdMgr.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/setup/ComponentIdMgr.java
index 0000000,0000000..7464a5a
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/setup/ComponentIdMgr.java
@@@ -1,0 -1,0 +1,101 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.setup;
++
++import java.util.HashMap ;
++import java.util.Map ;
++import java.util.UUID ;
++
++import org.seaborne.dboe.transaction.txn.ComponentId ;
++import org.slf4j.Logger ;
++import org.slf4j.LoggerFactory ;
++
++// Consistent name ->  ComponentId
++
++public class ComponentIdMgr {
++    private static Logger log = LoggerFactory.getLogger(ComponentIdMgr.class) ; 
++    
++    private static Map<String, Integer> names = new HashMap<>() ;  
++    static {
++        // Well know names.
++        setup(1, "SPO") ;
++        setup(2, "POS") ;
++        setup(3, "PSO") ;
++        setup(4, "OSP") ;
++        
++        setup(11, "GSPO") ;
++        setup(12, "GPOS") ;
++        setup(13, "GPSO") ;
++        setup(14, "GOSP") ;
++        
++        setup(21, "POSG") ;
++        setup(22, "PSOG") ;
++        setup(23, "OSPG") ;
++        setup(24, "SPOG") ;
++        
++        setup(30, "GPU") ;
++        
++        setup(40, "prefixes") ;
++        setup(41, "prefixes-data") ;
++        
++        setup(50, "nodes") ;
++        setup(51, "nodes-data") ;
++    }
++    
++    static void setup(int idx, String unitName) {
++        if ( names.containsKey(unitName) )
++            log.error("Name '"+unitName+"' is already registered") ;
++        names.put(unitName, idx) ;
++    }
++    
++    private Map<String, ComponentId> allocated = new HashMap<>() ;
++    
++    // Name to index mapping. 
++    static Map<String, String> mapper = new HashMap<>() ;
++    private final UUID base ;
++    
++    public ComponentIdMgr(UUID base) {
++        this.base = base ;
++    }
++    
++    public static int getIndex(String name) {
++        Integer idx = names.get(name) ;
++        if ( idx == null ) {
++            log.error("Unregistered '"+name+"'") ;
++            return -1 ;
++        }
++        return idx ;
++    }
++    
++    public ComponentId getComponentId(String name) {
++//        // Trace duplicates
++//        final String tracename = "SPO" ;
++//        if ( tracename.equals(name) )
++//            log.info("Name '"+name+"'") ;
++        if ( ! names.containsKey(name))
++            log.error("Name '"+name+"' is not registered") ;
++        if ( allocated.containsKey(name) ) {
++            log.error("ComponentId for '"+name+"' has already been allocated") ;
++            return allocated.get(name) ;
++        }
++        ComponentId cid = ComponentId.alloc(name, base, names.get(name)) ;
++        allocated.put(name, cid) ;
++        return cid ;
++    }
++}
++

http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/setup/StoreParams.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/setup/StoreParams.java
index 0000000,0000000..2c59757
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/setup/StoreParams.java
@@@ -1,0 -1,0 +1,441 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.setup;
++
++import java.util.Objects ;
++
++import org.seaborne.dboe.base.block.FileMode ;
++import org.seaborne.dboe.index.IndexParams ;
++import org.seaborne.tdb2.setup.StoreParamsBuilder.Item ;
++
++/** System parameters for a TDB database instance. 
++ * <p>
++ * Some parameters can be changed from run to run
++ * and some parameters can only be changed at the point the database is
++ * created.  
++ * <p>
++ * Getting paramters settings wrong can destroy a databse.   
++ * Alternating the block size is not encouraged and should only be
++ * done if necessary.  It can silently destroy a database if set
++ * to a different value than thatused to create the database.  The
++ * default value of 8Kbytes is good for almost use.
++ * 
++ * @see StoreParamsBuilder  for constructing StoreParams
++ * @see StoreParamsConst    for default values. 
++ */
++public class StoreParams implements IndexParams, StoreParamsDynamic
++{
++    /* These are items you can change JVM to JVM */
++    
++    /*package*/ final Item<FileMode>           fileMode ;
++    /*package*/ final Item<Integer>            blockSize ;
++    /*package*/ final Item<Integer>            blockReadCacheSize ;
++    /*package*/ final Item<Integer>            blockWriteCacheSize ;
++    /*package*/ final Item<Integer>            Node2NodeIdCacheSize ;
++    /*package*/ final Item<Integer>            NodeId2NodeCacheSize ;
++    /*package*/ final Item<Integer>            NodeMissCacheSize ;
++
++    /* These are items affect database layout and
++     * only can be applied when a database is created.
++     * They do not affect existing databases.
++     * If you want to, say, change the index structure,
++     * you'll need to use the index tools.  
++     */
++    
++    /*package*/ final Item<String>             nodeTableBaseName ;
++    
++    /*package*/ final Item<String>             primaryIndexTriples ;
++    /*package*/ final Item<String[]>           tripleIndexes ;
++    
++    /*package*/ final Item<String>             primaryIndexQuads ;
++    /*package*/ final Item<String[]>           quadIndexes ;
++    
++    /*package*/ final Item<String>             prefixTableBaseName ;
++    /*package*/ final Item<String>             primaryIndexPrefix ;
++    /*package*/ final Item<String[]>           prefixIndexes ;
++
++    /** Build StoreParams, starting from system defaults.
++     * 
++     * @return StoreParamsBuilder
++     */
++    public static StoreParamsBuilder builder() { return StoreParamsBuilder.create() ; }
++    
++    /** Build StoreParams, starting from given default values.
++     * 
++     * @return StoreParamsBuilder
++     */
++    public static StoreParamsBuilder builder(StoreParams params) { return StoreParamsBuilder.create(params) ; }
++    
++    /*package*/ StoreParams(Item<FileMode> fileMode, Item<Integer> blockSize,
++                            Item<Integer> blockReadCacheSize, Item<Integer> blockWriteCacheSize,
++                            Item<Integer> node2NodeIdCacheSize, Item<Integer> nodeId2NodeCacheSize,
++                            Item<Integer> nodeMissCacheSize,
++                            
++                            Item<String> nodeTableBaseName, 
++                            Item<String> primaryIndexTriples, Item<String[]> tripleIndexes,
++                            Item<String> primaryIndexQuads, Item<String[]> quadIndexes,
++                            
++                            Item<String> prefixTableBasename,
++                            Item<String> primaryIndexPrefix, Item<String[]> prefixIndexes) {
++        this.fileMode               = fileMode ;
++        this.blockSize              = blockSize ;
++        this.blockReadCacheSize     = blockReadCacheSize ;
++        this.blockWriteCacheSize    = blockWriteCacheSize ;
++        this.Node2NodeIdCacheSize   = node2NodeIdCacheSize ;
++        this.NodeId2NodeCacheSize   = nodeId2NodeCacheSize ;
++        this.NodeMissCacheSize      = nodeMissCacheSize ;
++
++        this.nodeTableBaseName      = nodeTableBaseName ;
++        
++        this.primaryIndexTriples    = primaryIndexTriples ;
++        this.tripleIndexes          = tripleIndexes ;
++        this.primaryIndexQuads      = primaryIndexQuads ;
++        this.quadIndexes            = quadIndexes ;
++        this.primaryIndexPrefix     = primaryIndexPrefix ;
++        this.prefixIndexes          = prefixIndexes ;
++        
++        this.prefixTableBaseName         = prefixTableBasename ;
++    }
++    
++    /** The system default settings. This is the normal set to use.
++     *  It is the set of values used when no StoreParams is provided,
++     *  which is the normal usage.
++     */
++    public static StoreParams getDftStoreParams() {
++        return StoreParamsConst.dftStoreParams ;
++    }
++    
++    /** A {@code StoreParams} that provides a smaller
++     * in-JVM foot print.  This is compatible with
++     * any database but it it is wise to use this consistently,
++     * that is, use when created and when opened later.
++     * It reduces cache sizes and runs the database in "direct"
++     * file mode so as not to use memory mapped files
++     * in addition to the JVM space.
++     */
++    public static StoreParams getSmallStoreParams() {
++        return StoreParamsConst.smallStoreParams ;
++    }
++
++    @Override
++    public FileMode getFileMode() {
++        return fileMode.value ;
++    }
++
++    @Override
++    public boolean isSetFileMode() {
++        return fileMode.isSet ;
++    }
++
++    @Override
++    public Integer getBlockSize() {
++        return blockSize.value ;
++    }
++
++    @Override
++    public Integer getBlockReadCacheSize() {
++        return blockReadCacheSize.value ;
++    }
++
++    @Override
++    public boolean isSetBlockReadCacheSize() {
++        return blockReadCacheSize.isSet ;
++    }
++
++    @Override
++    public Integer getBlockWriteCacheSize() {
++        return blockWriteCacheSize.value ;
++    }
++
++    @Override
++    public boolean isSetBlockWriteCacheSize() {
++        return blockWriteCacheSize.isSet ;
++    }
++
++    @Override
++    public Integer getNode2NodeIdCacheSize() {
++        return Node2NodeIdCacheSize.value ;
++    }
++
++    @Override
++    public boolean isSetNodeId2NodeCacheSize() {
++        return NodeId2NodeCacheSize.isSet ;
++    }
++
++    @Override
++    public boolean isSetNode2NodeIdCacheSize() {
++        return Node2NodeIdCacheSize.isSet ;
++    }
++
++    @Override
++    public Integer getNodeId2NodeCacheSize() {
++        return NodeId2NodeCacheSize.value ;
++    }
++
++    @Override
++    public Integer getNodeMissCacheSize() {
++        return NodeMissCacheSize.value ;
++    }
++
++    @Override
++    public boolean isSetNodeMissCacheSize() {
++        return NodeMissCacheSize.isSet ;
++    }
++
++    public String getNodeTableBaseName() {
++        return nodeTableBaseName.value ;
++    }
++    
++    public boolean isSetNodeTableBaseName() {
++        return nodeTableBaseName.isSet ;
++    }
++
++    public String getPrimaryIndexTriples() {
++        return primaryIndexTriples.value ;
++    }
++
++    public String[] getTripleIndexes() {
++        return tripleIndexes.value ;
++    }
++
++    public String getPrimaryIndexQuads() {
++        return primaryIndexQuads.value ;
++    }
++
++    public String[] getQuadIndexes() {
++        return quadIndexes.value ;
++    }
++
++    public String getPrefixTableBaseName() {
++        return prefixTableBaseName.value ;
++    }
++    
++    public boolean isSetPrefixBaseName() {
++        return prefixTableBaseName.isSet ;
++    }
++
++
++    
++    public String getPrimaryIndexPrefix() {
++        return primaryIndexPrefix.value ;
++    }
++
++    public String[] getPrefixIndexes() {
++        return prefixIndexes.value ;
++    }
++
++    @Override
++    public String toString() {
++        StringBuilder buff = new StringBuilder() ;
++        fmt(buff, "fileMode", getFileMode().toString(), fileMode.isSet) ;
++        fmt(buff, "blockSize", getBlockSize(), blockSize.isSet) ;
++        fmt(buff, "readCacheSize", getBlockReadCacheSize(), blockReadCacheSize.isSet) ;
++        fmt(buff, "writeCacheSize", getBlockWriteCacheSize(), blockWriteCacheSize.isSet) ;
++        fmt(buff, "Node2NodeIdCacheSize", getNode2NodeIdCacheSize(), Node2NodeIdCacheSize.isSet) ;
++        fmt(buff, "NodeId2NodeCacheSize", getNodeId2NodeCacheSize(), NodeId2NodeCacheSize.isSet) ;
++        fmt(buff, "NodeMissCacheSize", getNodeMissCacheSize(), NodeMissCacheSize.isSet) ;
++
++        fmt(buff, "nodeTableBaseName", getNodeTableBaseName(), nodeTableBaseName.isSet) ;
++        fmt(buff, "primaryIndexTriples", getPrimaryIndexTriples(), primaryIndexTriples.isSet) ;
++        fmt(buff, "tripleIndexes", getTripleIndexes(), tripleIndexes.isSet) ;
++        fmt(buff, "primaryIndexQuads", getPrimaryIndexQuads(), primaryIndexQuads.isSet) ;
++        fmt(buff, "quadIndexes", getQuadIndexes(), quadIndexes.isSet) ;
++        
++        fmt(buff, "prefixTableBaseName", getPrefixTableBaseName(), prefixTableBaseName.isSet) ;
++        fmt(buff, "primaryIndexPrefix", getPrimaryIndexPrefix(), primaryIndexPrefix.isSet) ;
++        fmt(buff, "prefixIndexes", getPrefixIndexes(), prefixIndexes.isSet) ;
++
++        return buff.toString() ;
++    }
++    
++    private void fmt(StringBuilder buff, String name, String[] strings, boolean isSet) {
++        String dftStr = "" ;
++        if ( ! isSet )
++            dftStr = "dft:" ;
++        buff.append(String.format("%-20s   %s[%s]\n", name, dftStr, String.join(", ", strings))) ;
++    }
++
++    private void fmt(StringBuilder buff, String name, String value, boolean isSet) {
++        String dftStr = "" ;
++        if ( ! isSet )
++            dftStr = "dft:" ;
++        buff.append(String.format("%-20s   %s%s\n", name, dftStr, value)) ;
++    }
++
++    private void fmt(StringBuilder buff, String name, int value, boolean isSet) {
++        String dftStr = "" ;
++        if ( ! isSet )
++            dftStr = "dft:" ;
++        buff.append(String.format("%-20s   %s%s\n", name, dftStr, value)) ;
++    }
++
++    /** Equality but ignore "isSet" */
++    public static boolean sameValues(StoreParams params1, StoreParams params2) {
++        if ( params1 == null && params2 == null )
++            return true ;
++        if ( params1 == null )
++            return false ;
++        if ( params2 == null )
++            return false ;
++        if ( !sameValues(params1.fileMode, params2.fileMode) )
++            return false ;
++        if ( !sameValues(params1.blockSize, params2.blockSize) )
++            return false ;
++        if ( !sameValues(params1.blockReadCacheSize, params2.blockReadCacheSize) )
++            return false ;
++        if ( !sameValues(params1.blockWriteCacheSize, params2.blockWriteCacheSize) )
++            return false ;
++        if ( !sameValues(params1.Node2NodeIdCacheSize, params2.Node2NodeIdCacheSize) )
++            return false ;
++        if ( !sameValues(params1.NodeId2NodeCacheSize, params2.NodeId2NodeCacheSize) )
++            return false ;
++        if ( !sameValues(params1.NodeMissCacheSize, params2.NodeMissCacheSize) )
++            return false ;
++        if ( !sameValues(params1.nodeTableBaseName, params2.nodeTableBaseName) )
++            return false ;
++        if ( !sameValues(params1.primaryIndexTriples, params2.primaryIndexTriples) )
++            return false ;
++        if ( !sameValues(params1.tripleIndexes, params2.tripleIndexes) )
++            return false ;
++        if ( !sameValues(params1.primaryIndexQuads, params2.primaryIndexQuads) )
++            return false ;
++        if ( !sameValues(params1.quadIndexes, params2.quadIndexes) )
++            return false ;
++        if ( !sameValues(params1.prefixTableBaseName, params2.prefixTableBaseName) )
++            return false ;
++        if ( !sameValues(params1.primaryIndexPrefix, params2.primaryIndexPrefix) )
++            return false ;
++        if ( !sameValues(params1.prefixIndexes, params2.prefixIndexes) )
++            return false ;
++        return true ;
++    }
++    
++    private static <X> boolean sameValues(Item<X> item1, Item<X> item2) {
++        return Objects.deepEquals(item1.value, item2.value) ; 
++    }
++
++    @Override
++    public int hashCode() {
++        final int prime = 31 ;
++        int result = 1 ;
++        result = prime * result + ((Node2NodeIdCacheSize == null) ? 0 : Node2NodeIdCacheSize.hashCode()) ;
++        result = prime * result + ((NodeId2NodeCacheSize == null) ? 0 : NodeId2NodeCacheSize.hashCode()) ;
++        result = prime * result + ((NodeMissCacheSize == null) ? 0 : NodeMissCacheSize.hashCode()) ;
++        result = prime * result + ((blockReadCacheSize == null) ? 0 : blockReadCacheSize.hashCode()) ;
++        result = prime * result + ((blockSize == null) ? 0 : blockSize.hashCode()) ;
++        result = prime * result + ((blockWriteCacheSize == null) ? 0 : blockWriteCacheSize.hashCode()) ;
++        result = prime * result + ((fileMode == null) ? 0 : fileMode.hashCode()) ;
++        result = prime * result + ((nodeTableBaseName == null) ? 0 : nodeTableBaseName.hashCode()) ;
++        result = prime * result + ((prefixTableBaseName == null) ? 0 : prefixTableBaseName.hashCode()) ;
++        result = prime * result + ((prefixIndexes == null) ? 0 : prefixIndexes.hashCode()) ;
++        result = prime * result + ((primaryIndexPrefix == null) ? 0 : primaryIndexPrefix.hashCode()) ;
++        result = prime * result + ((primaryIndexQuads == null) ? 0 : primaryIndexQuads.hashCode()) ;
++        result = prime * result + ((primaryIndexTriples == null) ? 0 : primaryIndexTriples.hashCode()) ;
++        result = prime * result + ((quadIndexes == null) ? 0 : quadIndexes.hashCode()) ;
++        result = prime * result + ((tripleIndexes == null) ? 0 : tripleIndexes.hashCode()) ;
++        return result ;
++    }
++
++    @Override
++    public boolean equals(Object obj) {
++        if ( this == obj )
++            return true ;
++        if ( obj == null )
++            return false ;
++        if ( getClass() != obj.getClass() )
++            return false ;
++        StoreParams other = (StoreParams)obj ;
++        if ( Node2NodeIdCacheSize == null ) {
++            if ( other.Node2NodeIdCacheSize != null )
++                return false ;
++        } else if ( !Node2NodeIdCacheSize.equals(other.Node2NodeIdCacheSize) )
++            return false ;
++        if ( NodeId2NodeCacheSize == null ) {
++            if ( other.NodeId2NodeCacheSize != null )
++                return false ;
++        } else if ( !NodeId2NodeCacheSize.equals(other.NodeId2NodeCacheSize) )
++            return false ;
++        if ( NodeMissCacheSize == null ) {
++            if ( other.NodeMissCacheSize != null )
++                return false ;
++        } else if ( !NodeMissCacheSize.equals(other.NodeMissCacheSize) )
++            return false ;
++        if ( blockReadCacheSize == null ) {
++            if ( other.blockReadCacheSize != null )
++                return false ;
++        } else if ( !blockReadCacheSize.equals(other.blockReadCacheSize) )
++            return false ;
++        if ( blockSize == null ) {
++            if ( other.blockSize != null )
++                return false ;
++        } else if ( !blockSize.equals(other.blockSize) )
++            return false ;
++        if ( blockWriteCacheSize == null ) {
++            if ( other.blockWriteCacheSize != null )
++                return false ;
++        } else if ( !blockWriteCacheSize.equals(other.blockWriteCacheSize) )
++            return false ;
++        if ( fileMode == null ) {
++            if ( other.fileMode != null )
++                return false ;
++        } else if ( !fileMode.equals(other.fileMode) )
++            return false ;
++        if ( nodeTableBaseName == null ) {
++            if ( other.nodeTableBaseName != null )
++                return false ;
++        } else if ( !nodeTableBaseName.equals(other.nodeTableBaseName) )
++            return false ;
++        if ( prefixTableBaseName == null ) {
++            if ( other.prefixTableBaseName != null )
++                return false ;
++        } else if ( !prefixTableBaseName.equals(other.prefixTableBaseName) )
++            return false ;
++        if ( prefixIndexes == null ) {
++            if ( other.prefixIndexes != null )
++                return false ;
++        } else if ( !prefixIndexes.equals(other.prefixIndexes) )
++            return false ;
++        if ( primaryIndexPrefix == null ) {
++            if ( other.primaryIndexPrefix != null )
++                return false ;
++        } else if ( !primaryIndexPrefix.equals(other.primaryIndexPrefix) )
++            return false ;
++        if ( primaryIndexQuads == null ) {
++            if ( other.primaryIndexQuads != null )
++                return false ;
++        } else if ( !primaryIndexQuads.equals(other.primaryIndexQuads) )
++            return false ;
++        if ( primaryIndexTriples == null ) {
++            if ( other.primaryIndexTriples != null )
++                return false ;
++        } else if ( !primaryIndexTriples.equals(other.primaryIndexTriples) )
++            return false ;
++        if ( quadIndexes == null ) {
++            if ( other.quadIndexes != null )
++                return false ;
++        } else if ( !quadIndexes.equals(other.quadIndexes) )
++            return false ;
++        if ( tripleIndexes == null ) {
++            if ( other.tripleIndexes != null )
++                return false ;
++        } else if ( !tripleIndexes.equals(other.tripleIndexes) )
++            return false ;
++        return true ;
++    }
++}
++

http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/setup/StoreParamsBuilder.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/setup/StoreParamsBuilder.java
index 0000000,0000000..3fb2f36
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/setup/StoreParamsBuilder.java
@@@ -1,0 -1,0 +1,308 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.setup;
++
++import org.seaborne.dboe.base.block.FileMode ;
++
++public class StoreParamsBuilder {
++    // Immutable.
++    static class Item<X> {
++        final X value  ;
++        final boolean isSet ;
++        
++        Item(X value, boolean isSet) {
++            this.value = value ;
++            this.isSet = isSet ;
++        }
++        @Override
++        public int hashCode() {
++            final int prime = 31 ;
++            int result = 1 ;
++            result = prime * result + (isSet ? 1231 : 1237) ;
++            result = prime * result + ((value == null) ? 0 : value.hashCode()) ;
++            return result ;
++        }
++        @Override
++        public boolean equals(Object obj) {
++            if ( this == obj )
++                return true ;
++            if ( obj == null )
++                return false ;
++            if ( getClass() != obj.getClass() )
++                return false ;
++            Item<?> other = (Item<?>)obj ;
++            if ( isSet != other.isSet )
++                return false ;
++            if ( value == null ) {
++                if ( other.value != null )
++                    return false ;
++            } else if ( !value.equals(other.value) )
++                return false ;
++            return true ;
++        }
++    }
++    
++    // See also StoreParamsConst.
++    /** Database and query configuration */ 
++    // Key names are the base name -  encode/decode may add a prefix.
++    
++    private Item<FileMode>           fileMode              = new Item<>(StoreParamsConst.fileMode, false) ;
++
++    private Item<Integer>            blockReadCacheSize    = new Item<>(StoreParamsConst.blockReadCacheSize, false) ;
++
++    private Item<Integer>            blockWriteCacheSize   = new Item<>(StoreParamsConst.blockWriteCacheSize, false) ;
++
++    private Item<Integer>            Node2NodeIdCacheSize  = new Item<>(StoreParamsConst.Node2NodeIdCacheSize, false) ;
++
++    private Item<Integer>            NodeId2NodeCacheSize  = new Item<>(StoreParamsConst.NodeId2NodeCacheSize, false) ;
++
++    private Item<Integer>            NodeMissCacheSize     = new Item<>(StoreParamsConst.NodeMissCacheSize, false) ;
++
++    /** Database layout - ignored after a database is created */
++
++    private Item<Integer>            blockSize             = new Item<>(StoreParamsConst.blockSize, false) ;
++
++    private Item<String>             nodeTableBaseName     = new Item<>(StoreParamsConst.nodeTableBaseName, false) ;
++    
++    private Item<String>             primaryIndexTriples   = new Item<>(StoreParamsConst.primaryIndexTriples, false) ;
++
++    private Item<String[]>           tripleIndexes         = new Item<>(StoreParamsConst.tripleIndexes, false) ;
++
++    private Item<String>             primaryIndexQuads     = new Item<>(StoreParamsConst.primaryIndexQuads, false) ;
++
++    private Item<String[]>           quadIndexes           = new Item<>(StoreParamsConst.quadIndexes, false) ;
++
++    private Item<String>             prefixTableBaseName   = new Item<>(StoreParamsConst.prefixTableBaseName, false) ;
++    
++    private Item<String>             primaryIndexPrefix    = new Item<>(StoreParamsConst.primaryIndexPrefix, false) ;
++
++    private Item<String[]>           prefixIndexes         = new Item<>(StoreParamsConst.prefixIndexes, false) ;
++    
++    public static StoreParamsBuilder create() {
++        return new StoreParamsBuilder() ;
++    }
++
++    public static StoreParamsBuilder create(StoreParams params) {
++        return new StoreParamsBuilder(params) ;
++    }
++
++    /** Using a base set of {@link StoreParams}, and update with dynamic parameters.
++     * 
++     * @param baseParams
++     * @param additionalParams
++     * @return StoreParams
++     */
++    
++    public static StoreParams modify(StoreParams baseParams, StoreParamsDynamic additionalParams) {
++        StoreParamsBuilder b = new StoreParamsBuilder(baseParams) ;
++        // Merge explicitly set params 
++        if ( additionalParams.isSetFileMode() )
++            b.fileMode(additionalParams.getFileMode()) ;
++        
++        if ( additionalParams.isSetBlockReadCacheSize() )
++            b.blockReadCacheSize(additionalParams.getBlockReadCacheSize()) ;
++
++        if ( additionalParams.isSetBlockWriteCacheSize() )
++            b.blockWriteCacheSize(additionalParams.getBlockWriteCacheSize()) ;
++        
++        if ( additionalParams.isSetNode2NodeIdCacheSize() )            
++            b.node2NodeIdCacheSize(additionalParams.getNode2NodeIdCacheSize()) ;
++        
++        if ( additionalParams.isSetNodeId2NodeCacheSize() )            
++            b.nodeId2NodeCacheSize(additionalParams.getNodeId2NodeCacheSize()) ;
++        
++        if ( additionalParams.isSetNodeMissCacheSize() )
++            b.nodeMissCacheSize(additionalParams.getNodeMissCacheSize()) ;
++
++        return b.build();
++    }
++    
++
++    private StoreParamsBuilder() {}
++    
++    /** Initial with a StoreParams as default values */
++    private StoreParamsBuilder(StoreParams other) {
++        this.fileMode               = other.fileMode ;
++        this.blockSize              = other.blockSize ;
++        this.blockReadCacheSize     = other.blockReadCacheSize ; 
++        this.blockWriteCacheSize    = other.blockWriteCacheSize ; 
++        this.Node2NodeIdCacheSize   = other.Node2NodeIdCacheSize ; 
++        this.NodeId2NodeCacheSize   = other.NodeId2NodeCacheSize ; 
++        this.NodeMissCacheSize      = other.NodeMissCacheSize ; 
++
++        this.nodeTableBaseName      = other.nodeTableBaseName ; 
++        
++        this.primaryIndexTriples    = other.primaryIndexTriples ; 
++        this.tripleIndexes          = other.tripleIndexes ; 
++        
++        this.primaryIndexQuads      = other.primaryIndexQuads ; 
++        this.quadIndexes            = other.quadIndexes ; 
++
++        this.prefixTableBaseName    = other.prefixTableBaseName ; 
++        this.primaryIndexPrefix     = other.primaryIndexPrefix ; 
++        this.prefixIndexes          = other.prefixIndexes ; 
++    }
++    
++    public StoreParams build() {
++        return new StoreParams(
++                 fileMode, blockSize, blockReadCacheSize, blockWriteCacheSize, 
++                 Node2NodeIdCacheSize, NodeId2NodeCacheSize, NodeMissCacheSize,
++                 nodeTableBaseName,
++                 primaryIndexTriples, tripleIndexes,
++                 primaryIndexQuads, quadIndexes, 
++                 prefixTableBaseName, primaryIndexPrefix,
++                 prefixIndexes) ;
++    }
++    
++    public FileMode getFileMode() {
++        return fileMode.value ;
++    }
++    
++    public StoreParamsBuilder fileMode(FileMode fileMode) {
++        this.fileMode = new Item<>(fileMode, true) ;
++        return this ;
++    }
++    
++    public int getBlockSize() {
++        return blockSize.value ;
++    }
++
++    public StoreParamsBuilder blockSize(int blockSize) {
++        this.blockSize = new Item<>(blockSize, true) ;
++        return this ;
++    }
++
++    public int getBlockReadCacheSize() {
++        return blockReadCacheSize.value ;
++    }
++
++    public StoreParamsBuilder blockReadCacheSize(int blockReadCacheSize) {
++        this.blockReadCacheSize = new Item<>(blockReadCacheSize, true) ;
++        return this ;
++    }
++
++    public int getBlockWriteCacheSize() {
++        return blockWriteCacheSize.value ;
++    }
++
++   public StoreParamsBuilder blockWriteCacheSize(int blockWriteCacheSize) {
++       this.blockWriteCacheSize = new Item<>(blockWriteCacheSize, true) ;
++       return this ;
++   }
++
++    public int getNode2NodeIdCacheSize() {
++        return Node2NodeIdCacheSize.value ;
++    }
++
++   public StoreParamsBuilder node2NodeIdCacheSize(int node2NodeIdCacheSize) {
++       Node2NodeIdCacheSize = new Item<>(node2NodeIdCacheSize, true) ;
++       return this ;
++   }
++
++    public int getNodeId2NodeCacheSize() {
++        return NodeId2NodeCacheSize.value ;
++    }
++
++   public StoreParamsBuilder nodeId2NodeCacheSize(int nodeId2NodeCacheSize) {
++       NodeId2NodeCacheSize = new Item<>(nodeId2NodeCacheSize, true) ;
++       return this ;
++   }
++
++    public int getNodeMissCacheSize() {
++        return NodeMissCacheSize.value ;
++    }
++
++   public StoreParamsBuilder nodeMissCacheSize(int nodeMissCacheSize) {
++       NodeMissCacheSize = new Item<>(nodeMissCacheSize, true) ;
++       return this ;
++   }
++
++   public String getNodeTableBaseName() {
++       return nodeTableBaseName.value ;
++   }
++   
++   public StoreParamsBuilder nodeTableBaseName(String nodeTableBaseName) {
++       this.nodeTableBaseName = new Item<>(nodeTableBaseName, true);
++       return this ;
++   }
++   
++   public String getPrimaryIndexTriples() {
++       return primaryIndexTriples.value ;
++   }
++
++   public StoreParamsBuilder primaryIndexTriples(String primaryIndexTriples) {
++       this.primaryIndexTriples = new Item<>(primaryIndexTriples, true) ;
++       return this ;
++   }
++
++   public String[] getTripleIndexes() {
++       return tripleIndexes.value ;
++   }
++
++   public StoreParamsBuilder tripleIndexes(String[] tripleIndexes) {
++       this.tripleIndexes = new Item<>(tripleIndexes, true) ;
++       return this ;
++   }
++
++   public String getPrimaryIndexQuads() {
++       return primaryIndexQuads.value ;
++   }
++
++   public StoreParamsBuilder primaryIndexQuads(String primaryIndexQuads) {
++       this.primaryIndexQuads = new Item<>(primaryIndexQuads, true) ;
++       return this ;
++   }
++
++    public String[] getQuadIndexes() {
++        return quadIndexes.value ;
++    }
++
++   public StoreParamsBuilder quadIndexes(String[] quadIndexes) {
++       this.quadIndexes = new Item<>(quadIndexes, true) ;
++       return this ;
++   }
++
++
++   public String getPreifixTableBaseName() {
++       return prefixTableBaseName.value ;
++   }
++   
++   public StoreParamsBuilder prefixTableBaseName(String prefixTableBaseName) {
++       this.prefixTableBaseName = new Item<>(prefixTableBaseName, true) ;
++       return this ;
++   }
++   
++   public String getPrimaryIndexPrefix() {
++        return primaryIndexPrefix.value ;
++    }
++
++   public StoreParamsBuilder primaryIndexPrefix(String primaryIndexPrefix) {
++       this.primaryIndexPrefix = new Item<>(primaryIndexPrefix, true) ;
++       return this ;
++   }
++
++    public String[] getPrefixIndexes() {
++        return prefixIndexes.value ;
++    }
++
++   public StoreParamsBuilder prefixIndexes(String[] prefixIndexes) {
++       this.prefixIndexes = new Item<>(prefixIndexes, true) ;
++       return this ;
++   }
++}
++

http://git-wip-us.apache.org/repos/asf/jena/blob/d9da3592/jena-db/tdb2/src/main/java/org/seaborne/tdb2/setup/StoreParamsCodec.java
----------------------------------------------------------------------
diff --cc jena-db/tdb2/src/main/java/org/seaborne/tdb2/setup/StoreParamsCodec.java
index 0000000,0000000..87653f9
new file mode 100644
--- /dev/null
+++ b/jena-db/tdb2/src/main/java/org/seaborne/tdb2/setup/StoreParamsCodec.java
@@@ -1,0 -1,0 +1,189 @@@
++/*
++ *  Licensed 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.
++ *
++ *  See the NOTICE file distributed with this work for additional
++ *  information regarding copyright ownership.
++ */
++
++package org.seaborne.tdb2.setup;
++
++import static org.seaborne.tdb2.setup.StoreParamsConst.* ;
++
++import java.io.BufferedOutputStream ;
++import java.io.FileOutputStream ;
++import java.io.IOException ;
++import java.io.OutputStream ;
++
++import org.apache.jena.atlas.AtlasException ;
++import org.apache.jena.atlas.io.IO ;
++import org.apache.jena.atlas.json.* ;
++import org.apache.jena.atlas.lib.Lib ;
++import org.seaborne.dboe.base.block.FileMode ;
++import org.seaborne.dboe.base.file.Location ;
++import org.seaborne.dboe.sys.Names;
++import org.seaborne.tdb2.TDBException ;
++
++/** Encode and decode {@link StoreParams} */ 
++public class StoreParamsCodec {
++    
++    /** Write to a file */ 
++    public static void write(Location location, StoreParams params) {
++        write(location.getPath(Names.TDB_CONFIG_FILE) ,params) ;
++    }
++    
++    /** Write to a file */ 
++    public static void write(String filename, StoreParams params) {
++        try (OutputStream out = new FileOutputStream(filename); 
++             OutputStream out2 = new BufferedOutputStream(out); ) {
++            JsonObject object = encodeToJson(params) ;
++            JSON.write(out2, object) ;
++            out2.write('\n') ;
++        }
++        catch (IOException ex) { IO.exception(ex); }
++    }
++
++    /** Read from a file */ 
++    public static StoreParams read(Location location) {
++        return read(location.getPath(Names.TDB_CONFIG_FILE)) ;
++    }
++    
++    /** Read from a file, if possible. */ 
++    public static StoreParams read(String filename) {
++        try {
++            JsonObject obj = JSON.read(filename) ;
++            return StoreParamsCodec.decode(obj) ;
++        } 
++        catch (JsonParseException ex) { return null ; }
++        catch (AtlasException ex) { return null ; }
++    }
++    
++    public static JsonObject encodeToJson(StoreParams params) {
++        JsonBuilder builder = new JsonBuilder() ;
++        builder.startObject("StoreParams") ;    // "StoreParams" is an internal alignment marker - not in the JSON.
++        
++        encode(builder, key(fFileMode),                 params.getFileMode().name()) ;
++        encode(builder, key(fBlockSize),                params.getBlockSize()) ;
++        encode(builder, key(fBlockReadCacheSize),       params.getBlockReadCacheSize()) ;
++        encode(builder, key(fBlockWriteCacheSize),      params.getBlockWriteCacheSize()) ;
++        encode(builder, key(fNode2NodeIdCacheSize),     params.getNode2NodeIdCacheSize()) ;
++        encode(builder, key(fNodeId2NodeCacheSize),     params.getNodeId2NodeCacheSize()) ;
++        encode(builder, key(fNodeMissCacheSize),        params.getNodeMissCacheSize()) ;
++        encode(builder, key(fNodeTableBaseName),        params.getNodeTableBaseName()) ;
++        encode(builder, key(fPrimaryIndexTriples),      params.getPrimaryIndexTriples()) ;
++        encode(builder, key(fTripleIndexes),            params.getTripleIndexes()) ;
++        encode(builder, key(fPrimaryIndexQuads),        params.getPrimaryIndexQuads()) ;
++        encode(builder, key(fQuadIndexes),              params.getQuadIndexes()) ;
++        encode(builder, key(fPrefixTableBaseName),      params.getPrefixTableBaseName()) ;
++        encode(builder, key(fPrimaryIndexPrefix),       params.getPrimaryIndexPrefix()) ;
++        encode(builder, key(fPrefixIndexes),            params.getPrefixIndexes()) ;
++        
++        builder.finishObject("StoreParams") ;
++        return (JsonObject)builder.build() ;
++    }
++
++    private static final String jsonKeyPrefix= "tdb." ;
++    
++    private static String key(String string) {
++        if ( string.startsWith(jsonKeyPrefix))
++            throw new TDBException("Key name already starts with '"+jsonKeyPrefix+"'") ;
++        return jsonKeyPrefix+string ;
++    }
++
++    private static String unkey(String string) {
++        if ( ! string.startsWith(jsonKeyPrefix) )
++            throw new TDBException("JSON key name does not start with '"+jsonKeyPrefix+"'") ;
++        return string.substring(jsonKeyPrefix.length()) ;
++    }
++
++    public static StoreParams decode(JsonObject json) {
++        StoreParamsBuilder builder = StoreParams.builder() ;
++        
++        for ( String key : json.keys() ) {
++            String short_key = unkey(key) ;
++            switch(short_key) {
++                case fFileMode :               builder.fileMode(FileMode.valueOf(getString(json, key))) ;   break ;
++                case fBlockSize:               builder.blockSize(getInt(json, key)) ;                       break ;
++                case fBlockReadCacheSize:      builder.blockReadCacheSize(getInt(json, key)) ;              break ;
++                case fBlockWriteCacheSize:     builder.blockWriteCacheSize(getInt(json, key)) ;             break ;
++                case fNode2NodeIdCacheSize:    builder.node2NodeIdCacheSize(getInt(json, key)) ;            break ;
++                case fNodeId2NodeCacheSize:    builder.nodeId2NodeCacheSize(getInt(json, key)) ;            break ;
++                case fNodeMissCacheSize:       builder.nodeMissCacheSize(getInt(json, key)) ;               break ;
++                
++                case fNodeTableBaseName:       builder.nodeTableBaseName(getString(json, key)) ;            break ;
++                case fPrimaryIndexTriples:     builder.primaryIndexTriples(getString(json, key)) ;          break ;
++                case fTripleIndexes:           builder.tripleIndexes(getStringArray(json, key)) ;           break ;
++                case fPrimaryIndexQuads:       builder.primaryIndexQuads(getString(json, key)) ;            break ;
++                case fQuadIndexes:             builder.quadIndexes(getStringArray(json, key)) ;             break ;
++                
++                case fPrefixTableBaseName:     builder.prefixTableBaseName(getString(json, key)) ;          break ;
++                case fPrimaryIndexPrefix:      builder.primaryIndexPrefix(getString(json, key)) ;           break ;
++                case fPrefixIndexes:           builder.prefixIndexes(getStringArray(json, key)) ;           break ;
++                
++                default:
++                    throw new TDBException("StoreParams key no recognized: "+key) ;
++            }
++        }
++        return builder.build() ;
++    }
++
++    // "Get or error" operations.
++    
++    private static String getString(JsonObject json, String key) {
++        if ( ! json.hasKey(key) )
++            throw new TDBException("StoreParamsCodec.getString: no such key: "+key) ;
++        String x = json.get(key).getAsString().value() ;
++        return x ;
++    }
++
++    private static Integer getInt(JsonObject json, String key) {
++        if ( ! json.hasKey(key) )
++            throw new TDBException("StoreParamsCodec.getInt: no such key: "+key) ;
++        Integer x = json.get(key).getAsNumber().value().intValue() ;
++        return x ;
++    }
++    
++    private static String[] getStringArray(JsonObject json, String key) {
++        if ( ! json.hasKey(key) )
++            throw new TDBException("StoreParamsCodec.getStringArray: no such key: "+key) ;
++        JsonArray a = json.get(key).getAsArray() ;
++        String[] x = new String[a.size()] ;
++        for ( int i = 0 ; i < a.size() ; i++ ) {
++            x[i] = a.get(i).getAsString().value() ;
++        }
++        return x ;
++    }
++
++    // Encode helper.
++    private static void encode(JsonBuilder builder, String name, Object value) {
++        if ( value instanceof Number ) {
++            long x = ((Number)value).longValue() ;
++            builder.key(name).value(x) ;
++            return ;
++        }
++        if ( value instanceof String ) {
++            builder.key(name).value(value.toString()) ;
++            return ;
++        }
++        if ( value instanceof String[] ) {
++            String[] x = (String[])value ;
++            builder.key(name) ;
++            builder.startArray() ;
++            for ( String s : x ) {
++                builder.value(s) ;
++            }
++            builder.finishArray() ;
++            return ;
++        }
++        throw new TDBException("Class of value not recognized: "+Lib.classShortName(value.getClass())) ;
++    }
++}


Mime
View raw message