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 2016/01/05 13:46:03 UTC

[09/20] jena git commit: JENA-1108 : jena-cmds module

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/main/java/tdb/tdbconfig.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/main/java/tdb/tdbconfig.java b/jena-cmds/src/main/java/tdb/tdbconfig.java
new file mode 100644
index 0000000..99aea15
--- /dev/null
+++ b/jena-cmds/src/main/java/tdb/tdbconfig.java
@@ -0,0 +1,250 @@
+/*
+ * 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 tdb;
+
+
+import java.util.List ;
+import java.util.Map ;
+
+import jena.cmd.ModVersion;
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+import org.apache.jena.atlas.lib.DateTimeUtils ;
+import org.apache.jena.graph.Node ;
+import org.apache.jena.shared.PrefixMapping ;
+import org.apache.jena.sparql.core.DatasetPrefixStorage ;
+import org.apache.jena.tdb.TDB ;
+import org.apache.jena.tdb.base.file.FileFactory ;
+import org.apache.jena.tdb.base.file.Location ;
+import org.apache.jena.tdb.base.objectfile.StringFile ;
+import org.apache.jena.tdb.setup.Build ;
+import org.apache.jena.tdb.solver.stats.Stats ;
+import org.apache.jena.tdb.solver.stats.StatsResults ;
+import org.apache.jena.tdb.store.DatasetGraphTDB ;
+import org.apache.jena.tdb.sys.DatasetControlNone ;
+
+import tdb.cmdline.CmdSub ;
+import tdb.cmdline.CmdTDB ;
+import tdb.cmdline.CmdTDBGraph ;
+import arq.cmdline.CmdARQ ;
+
+/** Tools to manage a TDB store.  Subcommand based. */
+public class tdbconfig extends CmdSub
+{
+    static final String CMD_CLEAN       = "clean" ;
+    static final String CMD_HELP        = "help" ;
+    static final String CMD_STATS       = "stats" ;
+    static final String CMD_NODES       = "nodes" ;
+    static final String CMD_INFO        = "info" ;
+    static final String CMD_PREFIXES    = "prefixes" ;
+    
+    static public void main(String... argv)
+    {
+        CmdTDB.init() ;
+        new tdbconfig(argv).exec();
+    }
+
+    protected tdbconfig(String[] argv)
+    {
+        super(argv) ;
+//        super.addSubCommand(CMD_CLEAN, new Exec()
+//          { @Override public void exec(String[] argv) { new tdbclean(argv).main() ; } }) ;
+        
+        super.addSubCommand(CMD_HELP, new Exec()
+        { /*@Override*/ @Override
+        public void exec(String[] argv) { new SubHelp(argv).mainRun() ; } }) ;
+        
+        super.addSubCommand(CMD_STATS, new Exec()
+        { /*@Override*/ @Override
+        public void exec(String[] argv) { new SubStats(argv).mainRun() ; } }) ;
+        
+        super.addSubCommand(CMD_NODES, new Exec()
+        { /*@Override*/ @Override
+        public void exec(String[] argv) { new SubNodes(argv).mainRun() ; } }) ;
+        
+        super.addSubCommand(CMD_INFO, new Exec()
+        { /*@Override*/ @Override
+        public void exec(String[] argv) { new SubInfo(argv).mainRun() ; } }) ;
+        
+        super.addSubCommand(CMD_PREFIXES, new Exec()
+        { /*@Override*/ @Override
+        public void exec(String[] argv) { new SubPrefixes(argv).mainRun() ; } }) ;
+
+        
+    }
+    
+    static class SubPrefixes extends CmdTDB
+    {
+        public SubPrefixes(String ... argv)
+        {
+            super(argv) ;
+            //super.addModule(modSymbol) ;
+        }
+
+        @Override
+        protected String getSummary()
+        {
+            return "tdbconfig prefixes" ;
+        }
+
+        @Override
+        protected void exec()
+        {
+            Location location = getLocation() ;
+            DatasetPrefixStorage prefixes = Build.makePrefixes(location, new DatasetControlNone()) ;
+            for ( String gn : prefixes.graphNames() )
+            {
+                System.out.println("Graph: "+gn) ;
+                PrefixMapping pmap = prefixes.getPrefixMapping(gn) ;
+                Map<String, String> x = pmap.getNsPrefixMap() ;
+                for ( String k : x.keySet() )
+                    System.out.printf("  %-10s %s\n", k+":", x.get(k)) ;
+            }
+        }
+    }
+    
+    // Subcommand : help
+    class SubHelp extends CmdARQ
+    {
+        public SubHelp(String ... argv)
+        {
+            super(argv) ;
+            //super.addModule(modSymbol) ;
+        }
+        
+        @Override
+        protected String getSummary()
+        {
+            return null ;
+        }
+
+        @Override
+        protected void exec()
+        {
+            IndentedWriter out = IndentedWriter.stdout ;
+            out.println("Sub-commands:") ;
+            out.incIndent() ;
+
+            for ( String name : subCommandNames() )
+            {
+                out.println(name) ; 
+            }
+            out.decIndent() ;
+            out.flush() ;
+        }
+
+        @Override
+        protected String getCommandName()
+        {
+            return "tdbconfig help" ;
+        }
+    }
+    
+    static class SubStats extends CmdTDBGraph
+    {
+        public SubStats(String ... argv)
+        {
+            super(argv) ;
+            //super.addModule(modSymbol) ;
+        }
+        
+        @Override
+        protected String getSummary()
+        {
+            return "tdbconfig stats" ;
+        }
+
+        @Override
+        protected void exec()
+        {
+            DatasetGraphTDB dsg = getDatasetGraphTDB() ;
+            Node gn = getGraphName() ;
+            StatsResults results = tdbstats.stats(dsg, gn) ;
+            Stats.write(System.out, results) ;
+        }
+
+        @Override
+        protected String getCommandName()
+        {
+            return "tdbconfig stats" ;
+        }
+    }
+    
+    static class SubNodes extends CmdTDB
+    {
+        public SubNodes(String ... argv)
+        {
+            super(argv) ;
+        }
+        
+        @Override
+        protected String getSummary()
+        {
+            return "tdbconfig nodes" ;
+        }
+
+        @Override
+        protected void exec()
+        {
+            List<String> args = positionals ;
+            for ( String x : args )
+            {
+                System.out.println("**** Object File: "+x) ;
+                StringFile objs = FileFactory.createStringFileDisk(x) ;
+                objs.dump() ;
+            }
+        }
+
+        @Override
+        protected String getCommandName()
+        {
+            return "tdbconfig nodes" ;
+        }
+    }
+
+    static class SubInfo extends CmdTDB
+    {
+        public SubInfo(String ... argv)
+        {
+            super(argv) ;
+        }
+        
+        @Override
+        protected String getSummary()
+        {
+            return "tdbconfig info" ;
+        }
+
+        @Override
+        protected void exec()
+        {
+            System.out.println("-- "+DateTimeUtils.nowAsString()+" --") ;
+            ModVersion v = new ModVersion(true) ;
+            v.addClass(TDB.class) ;
+            v.printVersionAndExit() ;
+        }
+
+        @Override
+        protected String getCommandName()
+        {
+            return "tdbconfig info" ;
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/main/java/tdb/tdbdump.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/main/java/tdb/tdbdump.java b/jena-cmds/src/main/java/tdb/tdbdump.java
new file mode 100644
index 0000000..093ae9e
--- /dev/null
+++ b/jena-cmds/src/main/java/tdb/tdbdump.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tdb;
+
+import org.apache.jena.riot.Lang ;
+import org.apache.jena.riot.RDFDataMgr ;
+import org.apache.jena.sparql.core.DatasetGraph ;
+import tdb.cmdline.CmdTDB ;
+
+public class tdbdump extends CmdTDB
+{
+    static public void main(String... argv)
+    { 
+        CmdTDB.init() ;
+        new tdbdump(argv).mainRun() ;
+    }
+
+    protected tdbdump(String[] argv)
+    {
+        super(argv) ;
+    }
+    
+    @Override
+    protected String getSummary()
+    {
+        return getCommandName()+" : Write N-Quads to stdout" ;
+    }
+
+    @Override
+    protected void exec()
+    {
+        DatasetGraph dsg = super.getDatasetGraphTDB() ;
+        RDFDataMgr.write(System.out, dsg, Lang.NQUADS) ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/main/java/tdb/tdbloader.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/main/java/tdb/tdbloader.java b/jena-cmds/src/main/java/tdb/tdbloader.java
new file mode 100644
index 0000000..37ba0e4
--- /dev/null
+++ b/jena-cmds/src/main/java/tdb/tdbloader.java
@@ -0,0 +1,138 @@
+/*
+ * 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 tdb ;
+
+import java.util.List ;
+
+import jena.cmd.ArgDecl;
+import jena.cmd.CmdException;
+
+import org.apache.jena.query.ARQ ;
+import org.apache.jena.riot.Lang ;
+import org.apache.jena.riot.RDFLanguages ;
+import org.apache.jena.tdb.TDB ;
+import org.apache.jena.tdb.TDBLoader ;
+import org.apache.jena.tdb.store.GraphTDB ;
+
+import tdb.cmdline.CmdTDB ;
+import tdb.cmdline.CmdTDBGraph ;
+
+public class tdbloader extends CmdTDBGraph {
+    // private static final ArgDecl argParallel = new ArgDecl(ArgDecl.NoValue, "parallel") ;
+    // private static final ArgDecl argIncremental = new ArgDecl(ArgDecl.NoValue, "incr", "incremental") ;
+    private static final ArgDecl argNoStats = new ArgDecl(ArgDecl.NoValue, "nostats") ;
+    private static final ArgDecl argStats = new ArgDecl(ArgDecl.HasValue,  "stats") ;
+
+    private boolean showProgress  = true ;
+    private boolean generateStats  = true ;
+    // private boolean doInParallel = false ;
+    // private boolean doIncremental = false ;
+
+    static public void main(String... argv) {
+        CmdTDB.init() ;
+        TDB.setOptimizerWarningFlag(false) ;
+        new tdbloader(argv).mainRun() ;
+    }
+
+    protected tdbloader(String[] argv) {
+        super(argv) ;
+//        super.getUsage().startCategory("Stats") ;
+        super.add(argNoStats, "--nostats", "Switch off statistics gathering") ;
+        super.add(argStats) ;   // Hidden argument
+        // super.add(argParallel, "--parallel",
+        // "Do rebuilding of secondary indexes in a parallel") ;
+        // super.add(argIncremental, "--incremental",
+        // "Do an incremental load (keep indexes during data load)") ;
+        // super.add(argStats, "--stats",
+        // "Generate statistics while loading (new graph only)") ;
+        // addModule(modRDFS) ;
+    }
+
+    @Override
+    protected void processModulesAndArgs() {
+        super.processModulesAndArgs() ;
+        // doInParallel = super.contains(argParallel) ;
+        // doIncremental = super.contains(argIncremental) ;
+    }
+
+    @Override
+    protected String getSummary() {
+        return getCommandName() + " [--desc DATASET | -loc DIR] FILE ..." ;
+    }
+
+    @Override
+    protected void exec() {
+        if ( isVerbose() ) {
+            System.out.println("Java maximum memory: " + Runtime.getRuntime().maxMemory()) ;
+            System.out.println(ARQ.getContext()) ;
+        }
+        if ( isVerbose() )
+            showProgress = true ;
+        if ( isQuiet() )
+            showProgress = false ;
+        if ( super.contains(argStats) ) {
+            if ( ! hasValueOfTrue(argStats) && ! hasValueOfFalse(argStats) )
+                throw new CmdException("Not a boolean value: "+getValue(argStats)) ;
+            generateStats = super.hasValueOfTrue(argStats) ;
+        }
+
+        if ( super.contains(argNoStats))
+            generateStats = false ;
+        
+        List<String> urls = getPositional() ;
+        if ( urls.size() == 0 )
+            urls.add("-") ;
+
+        if ( graphName == null ) {
+            loadQuads(urls) ;
+            return ;
+        }
+        
+        // There's a --graph.
+        // Check/warn that there are no quads formats mentioned
+        // (RIOT will take the default graph from quads).  
+        
+        for ( String url : urls ) {
+            Lang lang = RDFLanguages.filenameToLang(url) ;
+            if ( lang != null && RDFLanguages.isQuads(lang) ) {
+                System.err.println("Warning: Quads format given - only the default graph is loaded into the graph for --graph") ;
+                break ;
+            }
+        }
+        
+        loadNamedGraph(urls) ;
+    }
+
+//    void loadDefaultGraph(List<String> urls) {
+//        GraphTDB graph = getGraph() ;
+//        TDBLoader.load(graph, urls, showProgress) ;
+//        return ;
+//    }
+
+    void loadNamedGraph(List<String> urls) {
+        GraphTDB graph = getGraph() ;
+        TDBLoader.load(graph, urls, showProgress) ;
+        return ;
+    }
+
+    void loadQuads(List<String> urls) {
+        TDBLoader.load(getDatasetGraphTDB(), urls, showProgress, generateStats) ;
+        return ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/main/java/tdb/tdbnode.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/main/java/tdb/tdbnode.java b/jena-cmds/src/main/java/tdb/tdbnode.java
new file mode 100644
index 0000000..391c628
--- /dev/null
+++ b/jena-cmds/src/main/java/tdb/tdbnode.java
@@ -0,0 +1,84 @@
+/*
+ * 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 tdb;
+
+import java.util.Iterator ;
+
+import org.apache.jena.atlas.lib.Bytes ;
+import org.apache.jena.graph.Node ;
+import org.apache.jena.tdb.lib.NodeLib ;
+import org.apache.jena.tdb.store.DatasetGraphTDB ;
+import org.apache.jena.tdb.store.Hash ;
+import org.apache.jena.tdb.store.NodeId ;
+import org.apache.jena.tdb.store.nodetable.NodeTable ;
+import org.apache.jena.tdb.sys.SystemTDB ;
+import tdb.cmdline.CmdTDB ;
+
+public class tdbnode extends CmdTDB
+{
+    // Debugging tool.
+    static public void main(String... argv)
+    { 
+        CmdTDB.init() ;
+        new tdbnode(argv).mainRun() ;
+    }
+
+    protected tdbnode(String[] argv)
+    {
+        super(argv) ;
+    }
+
+    @Override
+    protected String getSummary()
+    {
+        return getCommandName()+" NodeId ..." ;
+    }
+
+    @Override
+    protected void exec()
+    {
+        DatasetGraphTDB dsg = getDatasetGraphTDB() ;
+        NodeTable nodeTable = dsg.getTripleTable().getNodeTupleTable().getNodeTable() ;
+        Iterator<String> iter = super.getPositional().iterator() ;
+        if ( ! iter.hasNext() )
+        {
+            System.err.println("No node ids") ;
+            return ;
+        }
+        
+        for ( ; iter.hasNext() ; )
+        {
+            String id = iter.next() ;
+            try {
+                long x = Long.parseLong(id) ;
+                NodeId nodeId = new NodeId(x) ;
+                Node n = nodeTable.getNodeForNodeId(nodeId) ;
+                //System.out.printf("%s [%d] => %s\n", id, x, n) ;
+
+                Hash h = new Hash(SystemTDB.LenNodeHash) ;
+                NodeLib.setHash(h, n) ;
+                String str = Bytes.asHex(h.getBytes()) ;
+                System.out.printf("%s %08d 0x%s # %s\n", id, x, str, n) ;
+            } catch (Exception ex)
+            {
+                System.out.println("Failed to decode: "+id) ;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/main/java/tdb/tdbquery.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/main/java/tdb/tdbquery.java b/jena-cmds/src/main/java/tdb/tdbquery.java
new file mode 100644
index 0000000..82ee3de
--- /dev/null
+++ b/jena-cmds/src/main/java/tdb/tdbquery.java
@@ -0,0 +1,60 @@
+/*
+ * 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 tdb;
+
+import org.apache.jena.tdb.TDB ;
+import tdb.cmdline.CmdTDB ;
+import tdb.cmdline.ModTDBDataset ;
+import arq.cmdline.ModDataset ;
+
+
+public class tdbquery extends arq.query
+{
+    // Inherits from arq.query so is not a CmdTDB.  Mixins for Java!
+    public static void main(String...argv)
+    {
+        CmdTDB.init() ;
+        new tdbquery(argv).mainRun() ;
+    }
+    
+    public tdbquery(String[] argv)
+    {
+        super(argv) ;
+        // Because this inherits from an ARQ command
+        super.modVersion.addClass(TDB.class) ;
+    }
+
+    @Override
+    protected String getSummary() 
+    { 
+        return getCommandName()+" --loc=<path> --query=<query>" ; 
+    }
+    
+    @Override
+    protected void processModulesAndArgs()
+    {
+        super.processModulesAndArgs() ;
+    }
+    
+    @Override
+    protected ModDataset setModDataset()
+    {
+        return new ModTDBDataset() ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/main/java/tdb/tdbrecovery.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/main/java/tdb/tdbrecovery.java b/jena-cmds/src/main/java/tdb/tdbrecovery.java
new file mode 100644
index 0000000..2621115
--- /dev/null
+++ b/jena-cmds/src/main/java/tdb/tdbrecovery.java
@@ -0,0 +1,54 @@
+/*
+ * 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 tdb;
+
+import org.apache.jena.tdb.TDB ;
+import org.apache.jena.tdb.store.DatasetGraphTDB ;
+import org.apache.jena.tdb.transaction.JournalControl ;
+import tdb.cmdline.CmdTDB ;
+
+public class tdbrecovery extends CmdTDB
+{
+    static public void main(String... argv)
+    { 
+        CmdTDB.init() ;
+        TDB.setOptimizerWarningFlag(false) ;
+        new tdbrecovery(argv).mainRun() ;
+    }
+
+    protected tdbrecovery(String[] argv)
+    {
+        super(argv) ;
+    }
+
+    @Override
+    protected String getSummary()
+    {
+        return getCommandName()+" --loc DIRECTORY\nRun database journal recovery." ;
+    }
+
+    @Override
+    protected void exec()
+    {
+        DatasetGraphTDB dsg = super.getDatasetGraphTDB() ;
+        // Just creating the DSG does a recovery so this is not (currently) necessary:
+        // This may change (not immediately recovering on start up).
+        JournalControl.recovery(dsg) ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/main/java/tdb/tdbreorder.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/main/java/tdb/tdbreorder.java b/jena-cmds/src/main/java/tdb/tdbreorder.java
new file mode 100644
index 0000000..8d9984a
--- /dev/null
+++ b/jena-cmds/src/main/java/tdb/tdbreorder.java
@@ -0,0 +1,124 @@
+/**
+ * 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 tdb;
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+import org.apache.jena.atlas.lib.FileOps ;
+import org.apache.jena.atlas.logging.LogCtl ;
+import org.apache.jena.graph.Triple ;
+import org.apache.jena.shared.PrefixMapping ;
+import org.apache.jena.shared.impl.PrefixMappingImpl ;
+import org.apache.jena.sparql.algebra.Op ;
+import org.apache.jena.sparql.algebra.op.OpBGP ;
+import org.apache.jena.sparql.algebra.op.OpQuadPattern ;
+import org.apache.jena.sparql.core.BasicPattern ;
+import org.apache.jena.sparql.engine.optimizer.StatsMatcher ;
+import org.apache.jena.sparql.engine.optimizer.reorder.ReorderLib ;
+import org.apache.jena.sparql.engine.optimizer.reorder.ReorderTransformation ;
+import org.apache.jena.sparql.engine.optimizer.reorder.ReorderTransformationSubstitution ;
+import org.apache.jena.sparql.serializer.SerializationContext ;
+import org.apache.jena.sparql.sse.SSE ;
+import org.apache.jena.sparql.sse.writers.WriterNode ;
+import org.apache.jena.tdb.sys.Names ;
+
+public class tdbreorder
+{
+    public static void main(String... args) {
+        if ( args.length != 2 ) {
+            System.err.println("Usage: PATTERN STATS") ;
+            System.exit(1) ;
+        }
+        LogCtl.enable(StatsMatcher.class) ;
+        LogCtl.enable(ReorderTransformationSubstitution.class) ;
+        
+        if ( args.length != 2 )
+        {
+            System.err.println("Usage: op stats") ; 
+            System.exit(1) ;
+        }
+            
+        String pattern = args[0] ;
+        String statsFile = args[1] ;
+        
+        Op op = SSE.readOp(pattern) ;
+
+        BasicPattern bgp ;
+        if ( op instanceof OpQuadPattern ) {
+            bgp = ((OpQuadPattern)op).getBasicPattern() ;
+        } else if ( op instanceof OpBGP ) {
+            bgp = ((OpBGP)op).getPattern() ;
+        }
+        else {
+            System.err.println("Not a quad or triple pattern") ;
+            System.exit(2) ;
+            bgp = null ;
+        }
+        
+        ReorderTransformation reorder = chooseReorder(statsFile) ;
+        //ReorderTransformation reorder = ReorderLib.fixed() ;
+        BasicPattern bgp2 = reorder.reorder(bgp) ;
+     
+        System.out.println() ;
+        
+        print(bgp) ;
+        System.out.println() ;
+        System.out.println(" ======== >>>>>>>>") ;
+        print(bgp2) ;
+        System.out.println() ;
+    }
+    
+    private static void print(BasicPattern bgp) {
+        IndentedWriter out = IndentedWriter.stdout;
+        
+        PrefixMapping pmap = new PrefixMappingImpl() ;
+        pmap.setNsPrefixes(SSE.defaultPrefixMapWrite) ;
+//        pmap.setNsPrefix("ppi", "http://landregistry.data.gov.uk/def/ppi/") ;
+//        pmap.setNsPrefix("common", "http://landregistry.data.gov.uk/def/common/") ;
+        
+        SerializationContext sCxt = SSE.sCxt(pmap) ;
+        
+        boolean first = true ;
+        for ( Triple t : bgp )
+        {
+            if ( !first )
+                out.print("\n") ;
+            else
+                first = false ;
+            // Adds (triple ...)
+            // SSE.write(buff.getIndentedWriter(), t) ;
+            out.print("(") ;
+            WriterNode.outputPlain(out, t, sCxt) ;
+            out.print(")") ;
+        }
+        out.flush();
+        
+    }
+    private static ReorderTransformation chooseReorder(String filename)
+    {
+        if ( filename.equals(Names.optFixed) )
+            return ReorderLib.fixed() ;
+        if ( filename.equals(Names.optNone) )
+            return ReorderLib.identity() ;
+        if ( FileOps.exists(filename) )
+            return ReorderLib.weighted(filename) ;
+        else
+            throw new RuntimeException("No such file: "+filename) ;
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/main/java/tdb/tdbstats.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/main/java/tdb/tdbstats.java b/jena-cmds/src/main/java/tdb/tdbstats.java
new file mode 100644
index 0000000..115c487
--- /dev/null
+++ b/jena-cmds/src/main/java/tdb/tdbstats.java
@@ -0,0 +1,103 @@
+/*
+ * 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 tdb;
+
+import java.util.Iterator ;
+
+import org.apache.jena.atlas.lib.tuple.Tuple ;
+import org.apache.jena.atlas.logging.Log ;
+import org.apache.jena.graph.Node ;
+import org.apache.jena.sparql.core.Quad ;
+import org.apache.jena.tdb.solver.SolverLib ;
+import org.apache.jena.tdb.solver.stats.Stats ;
+import org.apache.jena.tdb.solver.stats.StatsCollectorNodeId ;
+import org.apache.jena.tdb.solver.stats.StatsResults ;
+import org.apache.jena.tdb.store.DatasetGraphTDB ;
+import org.apache.jena.tdb.store.NodeId ;
+import org.apache.jena.tdb.store.nodetable.NodeTable ;
+import org.apache.jena.tdb.store.nodetupletable.NodeTupleTable ;
+import tdb.cmdline.CmdTDB ;
+import tdb.cmdline.CmdTDBGraph ;
+
+public class tdbstats extends CmdTDBGraph
+{
+    // tdbconfig?
+    static public void main(String... argv)
+    { 
+        CmdTDB.init() ;
+        new tdbstats(argv).mainRun() ;
+    }
+
+    protected tdbstats(String[] argv)
+    {
+        super(argv) ;
+    }
+    
+    @Override
+    protected String getSummary()
+    {
+        return null ;
+    }
+    
+    public static StatsResults stats(DatasetGraphTDB dsg, Node gn)
+    {
+        NodeTable nt = dsg.getTripleTable().getNodeTupleTable().getNodeTable() ;
+        StatsCollectorNodeId stats = new StatsCollectorNodeId(nt) ;
+        
+        if ( gn == null )
+        {
+            Iterator<Tuple<NodeId>> iter = dsg.getTripleTable().getNodeTupleTable().findAll() ;
+            for ( ; iter.hasNext(); )
+            {
+                Tuple<NodeId> t = iter.next() ;
+                stats.record(null, t.get(0), t.get(1), t.get(2)) ;
+            }
+        } else {
+            // If the union graph, then we need to scan all quads but with uniqueness.
+            boolean unionGraph = Quad.isUnionGraph(gn) ;
+            NodeId gnid = null ;
+            if ( ! unionGraph )
+            {
+                gnid = nt.getNodeIdForNode(gn) ;
+                if ( NodeId.isDoesNotExist(gnid) )
+                Log.warn(tdbstats.class, "No such graph: "+gn) ;
+            }
+                
+            NodeTupleTable ntt = dsg.getQuadTable().getNodeTupleTable() ;
+            Iterator<Tuple<NodeId>> iter = unionGraph
+                ? SolverLib.unionGraph(ntt)
+                : ntt.find(gnid, null, null, null) ;
+            for ( ; iter.hasNext(); )
+            {
+                Tuple<NodeId> t = iter.next() ;
+                stats.record(t.get(0), t.get(1), t.get(2), t.get(3)) ;
+            }
+        }
+        return stats.results() ;
+    }
+
+    @Override
+    protected void exec()
+    {
+        DatasetGraphTDB dsg = getDatasetGraphTDB() ;
+        Node gn = getGraphName() ;
+        StatsResults results = stats(dsg, gn) ;
+        Stats.write(System.out, results) ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/main/java/tdb/tdbupdate.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/main/java/tdb/tdbupdate.java b/jena-cmds/src/main/java/tdb/tdbupdate.java
new file mode 100644
index 0000000..464ec2e
--- /dev/null
+++ b/jena-cmds/src/main/java/tdb/tdbupdate.java
@@ -0,0 +1,61 @@
+/*
+ * 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 tdb;
+
+import arq.cmdline.ModDataset ;
+import jena.cmd.CmdException ;
+import org.apache.jena.sparql.core.DatasetGraph ;
+import org.apache.jena.tdb.TDB ;
+import org.apache.jena.tdb.transaction.TransactionManager ;
+import tdb.cmdline.CmdTDB ;
+import tdb.cmdline.ModTDBDataset ;
+
+public class tdbupdate extends arq.update
+{
+    // Inherits from arq.update so is not a CmdTDB.  Mixins for Java!
+    public static void main(String...argv)
+ {
+        CmdTDB.init();
+        // Do everything with flushing transactions.
+        TransactionManager.QueueBatchSize = 0;
+        new tdbupdate(argv).mainRun();
+    }
+
+    public tdbupdate(String[] argv) {
+        super(argv);
+        // Because this inherits from an ARQ command
+        CmdTDB.init();
+        super.modVersion.addClass(TDB.class);
+    }
+
+    @Override
+    protected void processModulesAndArgs() {
+        super.processModulesAndArgs();
+    }
+
+    @Override
+    protected ModDataset setModeDataset() {
+        return new ModTDBDataset();
+    }
+    
+    @Override
+    protected DatasetGraph dealWithNoDataset() {
+        throw new CmdException("No dataset provided") ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/main/java/tdb/tools/dumpbpt.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/main/java/tdb/tools/dumpbpt.java b/jena-cmds/src/main/java/tdb/tools/dumpbpt.java
new file mode 100644
index 0000000..269150e
--- /dev/null
+++ b/jena-cmds/src/main/java/tdb/tools/dumpbpt.java
@@ -0,0 +1,178 @@
+/*
+ * 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 tdb.tools ;
+
+import java.io.PrintStream ;
+import java.util.Arrays ;
+import java.util.Iterator ;
+import java.util.List ;
+
+import org.apache.jena.atlas.lib.Lib ;
+import org.apache.jena.atlas.lib.tuple.Tuple ;
+import org.apache.jena.atlas.logging.LogCtl ;
+import org.apache.jena.tdb.base.file.Location ;
+import org.apache.jena.tdb.base.record.Record ;
+import org.apache.jena.tdb.base.record.RecordFactory ;
+import org.apache.jena.tdb.index.IndexFactory ;
+import org.apache.jena.tdb.index.RangeIndex ;
+import org.apache.jena.tdb.index.bplustree.BPlusTree ;
+import org.apache.jena.tdb.lib.ColumnMap ;
+import org.apache.jena.tdb.store.NodeId ;
+import org.apache.jena.tdb.store.tupletable.TupleIndex ;
+import org.apache.jena.tdb.store.tupletable.TupleIndexRecord ;
+import org.apache.jena.tdb.sys.Names ;
+import org.apache.jena.tdb.sys.SystemTDB ;
+
+import arq.cmdline.CmdARQ;
+import tdb.cmdline.ModLocation ;
+
+public class dumpbpt extends CmdARQ {
+    ModLocation modLocation = new ModLocation() ;
+
+    static public void main(String... argv) {
+        LogCtl.setLog4j() ;
+        new dumpbpt(argv).mainRun() ;
+    }
+
+    protected dumpbpt(String[] argv) {
+        super(argv) ;
+        super.addModule(modLocation) ;
+    }
+
+    @Override
+    protected void processModulesAndArgs() {
+        if ( modVersion.getVersionFlag() )
+            modVersion.printVersionAndExit() ;
+        if ( modLocation.getLocation() == null )
+            cmdError("Location required") ;
+        if ( super.getPositional().size() == 0 )
+            cmdError("No index specified") ;
+    }
+
+    @Override
+    protected String getSummary() {
+        return getCommandName() + " --loc=DIR IndexName" ;
+    }
+
+    @Override
+    protected String getCommandName() {
+        return Lib.className(this) ;
+    }
+
+    @Override
+    protected void exec() {
+        List<String> tripleIndexes = Arrays.asList(Names.tripleIndexes) ;
+        List<String> quadIndexes = Arrays.asList(Names.quadIndexes) ;
+        Location loc = modLocation.getLocation() ;
+
+        // The name is the order.
+        for ( String indexName : super.getPositional() ) {
+            String primary ;
+            if ( indexName.length() == 3 ) {
+                primary = Names.primaryIndexTriples ;
+            } else if ( indexName.length() == 4 ) {
+                primary = Names.primaryIndexQuads ;
+            } else {
+                cmdError("Wrong length: " + indexName) ;
+                primary = null ;
+            }
+
+            int keySubLen = SystemTDB.SizeOfNodeId ;
+            int keyUnitLen = indexName.length() ;
+            int keyLength = keySubLen * keyUnitLen ;
+            int valueLength = 0 ;
+
+            RecordFactory rf = new RecordFactory(keyLength, valueLength) ;
+            RangeIndex rIndex = IndexFactory.buildRangeIndex(loc, indexName, rf) ;
+            BPlusTree bpt = (BPlusTree)rIndex ;
+
+            if ( false ) {
+                System.out.println("---- Index structure") ;
+                bpt.dump() ;
+            }
+            if ( true ) {
+                System.out.println("---- Index contents") ;
+                Iterator<Record> iter = bpt.iterator() ;
+                if ( !iter.hasNext() )
+                    System.out.println("<<Empty>>") ;
+
+                for ( ; iter.hasNext() ; ) {
+                    Record r = iter.next() ;
+                    printRecord("", System.out, r, keyUnitLen) ;
+                }
+            }
+
+            // Check.
+            Iterator<Record> iterCheck = bpt.iterator() ;
+            Record r1 = null ;
+            int i = 0 ;
+            for ( ; iterCheck.hasNext() ; ) {
+                Record r2 = iterCheck.next() ;
+                i++ ;
+
+                if ( r1 != null ) {
+                    if ( !Record.keyLT(r1, r2) ) {
+                        System.err.println("key error@ " + i) ;
+                        printRecord("  ", System.err, r1, keyUnitLen) ;
+                        printRecord("  ", System.err, r2, keyUnitLen) ;
+                    }
+                }
+                r1 = r2 ;
+            }
+
+            if ( false ) {
+                // Dump in tuple order.
+                TupleIndex tupleIndex = new TupleIndexRecord(primary.length(), new ColumnMap(primary, indexName), indexName,
+                                                             rIndex.getRecordFactory(), rIndex) ;
+                if ( true ) {
+                    System.out.println("---- Tuple contents") ;
+                    Iterator<Tuple<NodeId>> iter2 = tupleIndex.all() ;
+                    if ( !iter2.hasNext() )
+                        System.out.println("<<Empty>>") ;
+
+                    for ( ; iter2.hasNext() ; ) {
+                        Tuple<NodeId> row = iter2.next() ;
+                        System.out.println(row) ;
+                    }
+                }
+            }
+        }
+    }
+
+    private static void printRecord(String label, PrintStream out, Record r, int keyUnitLen) {
+        // out.println(r) ;
+
+        int keySubLen = r.getKey().length / keyUnitLen ;
+        if ( label != null )
+            out.print(label) ;
+        for ( int i = 0 ; i < keyUnitLen ; i++ ) {
+            if ( i != 0 )
+                out.print(" ") ;
+
+            // Print in chunks
+            int k = i * keySubLen ;
+            for ( int j = k ; j < k + keySubLen ; j++ )
+                out.printf("%02x", r.getKey()[j]) ;
+
+            // long x = Bytes.getLong(r.getKey(), i*SystemTDB.SizeOfNodeId) ;
+            // System.out.printf("%016x", x) ;
+        }
+        out.println() ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/main/java/tdb/tools/dumpnodetable.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/main/java/tdb/tools/dumpnodetable.java b/jena-cmds/src/main/java/tdb/tools/dumpnodetable.java
new file mode 100644
index 0000000..31f6309
--- /dev/null
+++ b/jena-cmds/src/main/java/tdb/tools/dumpnodetable.java
@@ -0,0 +1,182 @@
+/*
+ * 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 tdb.tools ;
+
+import java.io.OutputStream ;
+import java.util.Arrays ;
+import java.util.Iterator ;
+import java.util.List ;
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+import org.apache.jena.atlas.lib.Lib ;
+import org.apache.jena.atlas.lib.Pair ;
+import org.apache.jena.atlas.logging.Log ;
+import org.apache.jena.atlas.logging.LogCtl ;
+import org.apache.jena.graph.Node ;
+import org.apache.jena.graph.Node_Literal ;
+import org.apache.jena.sparql.util.FmtUtils ;
+import org.apache.jena.tdb.StoreConnection ;
+import org.apache.jena.tdb.base.file.Location ;
+import org.apache.jena.tdb.setup.Build ;
+import org.apache.jena.tdb.store.DatasetGraphTDB ;
+import org.apache.jena.tdb.store.NodeId ;
+import org.apache.jena.tdb.store.nodetable.NodeTable ;
+import org.apache.jena.tdb.sys.Names ;
+import org.apache.jena.tdb.sys.SystemTDB ;
+
+import arq.cmdline.CmdARQ;
+import tdb.cmdline.ModLocation ;
+
+public class dumpnodetable extends CmdARQ {
+    ModLocation modLocation = new ModLocation() ;
+
+    static public void main(String... argv) {
+        LogCtl.setLog4j() ;
+        new dumpnodetable(argv).mainRun() ;
+    }
+
+    @Override
+    protected void exec() {
+        List<String> tripleIndexes = Arrays.asList(Names.tripleIndexes) ;
+        List<String> quadIndexes = Arrays.asList(Names.quadIndexes) ;
+        Location loc = modLocation.getLocation() ;
+
+        StoreConnection sConn = StoreConnection.make(loc) ;
+        DatasetGraphTDB dsg = sConn.getBaseDataset() ;
+        NodeTable nodeTable = dsg.getQuadTable().getNodeTupleTable().getNodeTable() ;
+        dump(System.out, nodeTable) ;
+    }
+
+    protected dumpnodetable(String[] argv) {
+        super(argv) ;
+        super.addModule(modLocation) ;
+    }
+
+    public static void dumpNodes(OutputStream w, String location) {
+        dump(w, location, Names.indexNode2Id, SystemTDB.Node2NodeIdCacheSize, Names.indexId2Node, SystemTDB.NodeId2NodeCacheSize,
+             SystemTDB.NodeMissCacheSize) ;
+    }
+
+    public static void dumpPrefixes(OutputStream w, String location) {
+        dump(w, location, Names.prefixNode2Id, 100, Names.prefixId2Node, 100, 10) ;
+    }
+
+    public static void dump(OutputStream w, String location, String indexNode2Id, int node2NodeIdCacheSize, String indexId2Node,
+                            int nodeId2NodeCacheSize, //
+
+                            int sizeNodeMissCacheSize) {
+        NodeTable nodeTable = Build.makeNodeTable(Location.create(location), indexNode2Id, node2NodeIdCacheSize, indexId2Node,
+                                                  nodeId2NodeCacheSize, sizeNodeMissCacheSize) ;
+    }
+
+    public static void dump(OutputStream w, NodeTable nodeTable) {
+        // Better to hack the indexes?
+        Iterator<Pair<NodeId, Node>> iter = nodeTable.all() ;
+        long count = 0 ;
+        try (IndentedWriter iw = new IndentedWriter(w)) {
+            for ( ; iter.hasNext() ; ) {
+                Pair<NodeId, Node> pair = iter.next() ;
+                iw.print(pair.car().toString()) ;
+                iw.print(" : ") ;
+                // iw.print(pair.cdr()) ;
+                Node n = pair.cdr() ;
+                String $ = stringForNode(n) ;
+                iw.print($) ;
+                iw.println() ;
+                count++ ;
+            }
+            iw.println() ;
+            iw.printf("Total: " + count) ;
+            iw.println() ;
+            iw.flush() ;
+        }
+    }
+
+    private static String stringForNode(Node n) {
+        if ( n == null )
+            return "<<null>>" ;
+
+        if ( n.isBlank() )
+            return "_:" + n.getBlankNodeLabel() ;
+
+        if ( n.isLiteral() )
+            return stringForLiteral((Node_Literal)n) ;
+
+        if ( n.isURI() ) {
+            String uri = n.getURI() ;
+            return stringForURI(uri) ;
+        }
+
+        if ( n.isVariable() )
+            return "?" + n.getName() ;
+
+        if ( n.equals(Node.ANY) )
+            return "ANY" ;
+
+        Log.warn(FmtUtils.class, "Failed to turn a node into a string: " + n) ;
+        return n.toString() ;
+    }
+
+    public static String stringForURI(String uri) {
+        return "<" + uri + ">" ;
+    }
+
+    public static String stringForLiteral(Node_Literal literal) {
+        String datatype = literal.getLiteralDatatypeURI() ;
+        String lang = literal.getLiteralLanguage() ;
+        String s = literal.getLiteralLexicalForm() ;
+
+        StringBuilder sbuff = new StringBuilder() ;
+        sbuff.append("\"") ;
+        FmtUtils.stringEsc(sbuff, s, true) ;
+        sbuff.append("\"") ;
+
+        // Format the language tag
+        if ( lang != null && lang.length() > 0 ) {
+            sbuff.append("@") ;
+            sbuff.append(lang) ;
+        }
+
+        if ( datatype != null ) {
+            sbuff.append("^^") ;
+            sbuff.append(stringForURI(datatype)) ;
+        }
+
+        return sbuff.toString() ;
+    }
+
+    @Override
+    protected void processModulesAndArgs() {
+        if ( modVersion.getVersionFlag() )
+            modVersion.printVersionAndExit() ;
+        if ( modLocation.getLocation() == null )
+            cmdError("Location required") ;
+    }
+
+    @Override
+    protected String getSummary() {
+        return getCommandName() + " --loc=DIR IndexName" ;
+    }
+
+    @Override
+    protected String getCommandName() {
+        return Lib.className(this) ;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/main/java/tdb/tools/tdbgenindex.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/main/java/tdb/tools/tdbgenindex.java b/jena-cmds/src/main/java/tdb/tools/tdbgenindex.java
new file mode 100644
index 0000000..9371ce2
--- /dev/null
+++ b/jena-cmds/src/main/java/tdb/tools/tdbgenindex.java
@@ -0,0 +1,86 @@
+/**
+ * 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 tdb.tools ;
+
+import java.util.Iterator ;
+
+import org.apache.jena.atlas.lib.Lib ;
+import org.apache.jena.atlas.lib.tuple.Tuple ;
+import org.apache.jena.tdb.base.file.Location ;
+import org.apache.jena.tdb.store.NodeId ;
+import org.apache.jena.tdb.store.tupletable.TupleIndex ;
+import org.apache.jena.tdb.sys.Names ;
+import org.apache.jena.tdb.sys.SetupTDB ;
+import org.apache.jena.tdb.sys.SystemTDB ;
+
+/** copy one index to another, possibly changing the order */
+public class tdbgenindex {
+    public static void main(String... argv) {
+        // Usage: srcLocation indexName dstLocation indexName
+        if ( argv.length != 4 ) {
+            System.err.println("Usage: " + Lib.classShortName(tdbgenindex.class) + " srcLocation srcIndex dstLocation dstIndex") ;
+            System.exit(1) ;
+        }
+
+        Location srcLoc = Location.create(argv[0]) ;
+        String srcIndexName = argv[1] ;
+
+        Location dstLoc = Location.create(argv[2]) ;
+        String dstIndexName = argv[3] ;
+
+        int readCacheSize = 0 ;
+        int writeCacheSize = -1 ;
+
+        if ( srcIndexName.length() != dstIndexName.length() ) {
+            System.err.println("srcIndexName.length() != dstIndexName.length() " + srcIndexName + " :: " + dstIndexName) ;
+            System.exit(1) ;
+        }
+
+        String primary ;
+        int dftKeyLength ;
+        int dftValueLength ;
+
+        if ( srcIndexName.length() == 3 ) {
+            primary = Names.primaryIndexTriples ;
+            dftKeyLength = SystemTDB.LenIndexTripleRecord ;
+            dftValueLength = 0 ;
+        } else if ( srcIndexName.length() == 4 ) {
+            primary = Names.primaryIndexQuads ;
+            dftKeyLength = SystemTDB.LenIndexQuadRecord ;
+            dftValueLength = 0 ;
+        } else {
+            System.err.println("indexlength != 3 or 4") ;
+            System.exit(1) ;
+            primary = null ;
+            dftKeyLength = 0 ;
+            dftValueLength = 0 ;
+        }
+
+        TupleIndex srcIdx = SetupTDB.makeTupleIndex(srcLoc, primary, srcIndexName, srcIndexName, dftKeyLength) ;
+        TupleIndex dstIdx = SetupTDB.makeTupleIndex(dstLoc, primary, dstIndexName, dstIndexName, dftKeyLength) ;
+
+        Iterator<Tuple<NodeId>> iter = srcIdx.all() ;
+        for ( ; iter.hasNext() ; ) {
+            Tuple<NodeId> tuple = iter.next() ;
+            dstIdx.add(tuple) ;
+        }
+        srcIdx.close() ;
+        dstIdx.close() ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/test/java/jena/cmd/TS_Cmd.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/test/java/jena/cmd/TS_Cmd.java b/jena-cmds/src/test/java/jena/cmd/TS_Cmd.java
new file mode 100644
index 0000000..bfaf8fe
--- /dev/null
+++ b/jena-cmds/src/test/java/jena/cmd/TS_Cmd.java
@@ -0,0 +1,36 @@
+/**
+ * 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 jena.cmd;
+
+import org.apache.jena.atlas.logging.LogCtl ;
+import org.junit.runner.RunWith ;
+import org.junit.runners.Suite ;
+import org.junit.runners.Suite.SuiteClasses ;
+
+@RunWith(Suite.class)
+@SuiteClasses( {
+    TestCmdLine.class
+    , Test_schemagen.class
+    , Test_rdfcat.class
+})
+
+public class TS_Cmd
+{
+    static { LogCtl.setLog4j(); }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/test/java/jena/cmd/TestCmdLine.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/test/java/jena/cmd/TestCmdLine.java b/jena-cmds/src/test/java/jena/cmd/TestCmdLine.java
new file mode 100644
index 0000000..a5ef521
--- /dev/null
+++ b/jena-cmds/src/test/java/jena/cmd/TestCmdLine.java
@@ -0,0 +1,104 @@
+/*
+ * 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 jena.cmd;
+import java.util.Iterator ;
+
+import jena.cmd.ArgDecl;
+import jena.cmd.CmdLineArgs;
+
+import org.junit.Test ;
+import static org.junit.Assert.* ;
+
+public class TestCmdLine
+{
+    @Test public void test_Simple1()
+    {
+        String args[] = new String[]{""} ;
+        CmdLineArgs cl = new CmdLineArgs(args) ;
+        cl.process() ;
+    }
+    
+    @Test public void test_Flag1()
+    {
+        String args[] = new String[]{ ""} ;
+        CmdLineArgs cl = new CmdLineArgs(args) ;
+        ArgDecl argA = new ArgDecl(false, "-a") ;
+        cl.add(argA) ;
+        cl.process() ;
+        assertTrue("-a argument found" , ! cl.contains(argA) ) ; 
+    }
+    
+    @Test public void test_Flag2()
+    {
+        String args[] = new String[]{ "-a"} ;
+        CmdLineArgs cl = new CmdLineArgs(args) ;
+        ArgDecl argA = new ArgDecl(false, "-a") ;
+        cl.add(argA) ;
+        cl.process() ;
+        assertTrue("No -a argument found" , cl.contains(argA) ) ; 
+    }
+
+    @Test public void test_Flag3()
+    {
+        String args[] = new String[]{ "-a", "filename"} ;
+        CmdLineArgs cl = new CmdLineArgs(args) ;
+        ArgDecl argA = new ArgDecl(false, "-a") ;
+        cl.add(argA) ;
+        cl.process() ;
+        assertTrue("No -a argument found" , cl.contains(argA) ) ; 
+    }
+    
+    @Test public void test_Arg1()
+    {
+        String args[] = new String[]{ ""} ;
+        CmdLineArgs cl = new CmdLineArgs(args) ;
+        ArgDecl argA = new ArgDecl(true, "-arg") ;
+        cl.add(argA) ;
+        cl.process() ;
+        assertTrue("-arg argument found" , ! cl.contains(argA) ) ; 
+    }
+    
+    @Test public void test_Arg2()
+    {
+        String args[] = new String[]{ "-arg=ARG", "filename"} ;
+        CmdLineArgs cl = new CmdLineArgs(args) ;
+        ArgDecl argA = new ArgDecl(true, "arg") ;
+        cl.add(argA) ;
+        cl.process() ;
+        assertTrue("No -arg= argument found" , cl.contains(argA) ) ; 
+        assertEquals("", cl.getValue(argA) , "ARG") ;
+        assertEquals("", cl.getArg("arg").getValue() , "ARG") ;
+    }
+    
+    @Test public void test_nArg1()
+    {
+        String args[] = new String[]{ "-arg=V1", "--arg=V2", "-v"} ;
+        CmdLineArgs cl = new CmdLineArgs(args) ;
+        ArgDecl argA = new ArgDecl(true, "-arg") ;
+        cl.add(argA) ;
+        ArgDecl argV = new ArgDecl(false, "-v") ;
+        cl.add(argV) ;
+        cl.process() ;
+        assertTrue("No -arg= argument found" , cl.contains(argA) ) ;
+        
+        Iterator<String> iter = cl.getValues("arg").iterator() ;
+        assertEquals("Argument 1", iter.next() , "V1") ;
+        assertEquals("Argument 2", iter.next() , "V2") ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/498b2264/jena-cmds/src/test/java/jena/cmd/Test_rdfcat.java
----------------------------------------------------------------------
diff --git a/jena-cmds/src/test/java/jena/cmd/Test_rdfcat.java b/jena-cmds/src/test/java/jena/cmd/Test_rdfcat.java
new file mode 100644
index 0000000..950d06f
--- /dev/null
+++ b/jena-cmds/src/test/java/jena/cmd/Test_rdfcat.java
@@ -0,0 +1,291 @@
+/*
+ * 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 jena.cmd;
+
+import static org.junit.Assert.assertEquals ;
+import static org.junit.Assert.assertTrue ;
+
+import java.io.ByteArrayOutputStream ;
+import java.io.OutputStream ;
+import java.io.StringReader ;
+import java.util.ArrayList ;
+import java.util.List ;
+
+import jena.rdfcat;
+import org.apache.jena.rdf.model.Model ;
+import org.apache.jena.rdf.model.ModelFactory ;
+import org.junit.AfterClass ;
+import org.junit.BeforeClass ;
+import org.junit.Test ;
+
+@SuppressWarnings("deprecation")
+public class Test_rdfcat
+{
+    // Switch off the banner during testing.
+    @BeforeClass
+    public static void setUp() {
+        jena.rdfcat.suppressDeprecationBanner = true ;
+    }
+    
+    @AfterClass
+    public static void tearDown() {
+        jena.rdfcat.suppressDeprecationBanner = false ;
+    }
+    
+    @Test
+    public void testAbbreviationTable()
+        {
+        assertEquals( "RDF/XML", jena.rdfcat.unabbreviate.get( "x" ) );
+        assertEquals( "RDF/XML", jena.rdfcat.unabbreviate.get( "rdf" ) );
+        assertEquals( "RDF/XML", jena.rdfcat.unabbreviate.get( "rdfxml" ) );
+        assertEquals( "RDF/XML", jena.rdfcat.unabbreviate.get( "xml" ) );
+        assertEquals( "N3", jena.rdfcat.unabbreviate.get( "n3" ) );
+        assertEquals( "N3", jena.rdfcat.unabbreviate.get( "n" ) );
+        assertEquals( "N3", jena.rdfcat.unabbreviate.get( "ttl" ) );
+        assertEquals( "N-TRIPLE", jena.rdfcat.unabbreviate.get( "ntriples" ) );
+        assertEquals( "N-TRIPLE", jena.rdfcat.unabbreviate.get( "ntriple" ) );
+        assertEquals( "N-TRIPLE", jena.rdfcat.unabbreviate.get( "t" ) );
+        assertEquals( "RDF/XML-ABBREV", jena.rdfcat.unabbreviate.get( "owl" ) );
+        assertEquals( "RDF/XML-ABBREV", jena.rdfcat.unabbreviate.get( "abbrev" ) );
+        }
+
+    @Test
+    public void testExistingLanguage()
+        {
+        assertEquals( "RDF/XML", jena.rdfcat.getCheckedLanguage( "x" ) );
+        assertEquals( "RDF/XML", jena.rdfcat.getCheckedLanguage( "xml" ) );
+        assertEquals( "RDF/XML-ABBREV", jena.rdfcat.getCheckedLanguage( "owl" ) );
+        assertEquals( "N3", jena.rdfcat.getCheckedLanguage( "N3" ) );
+        assertEquals( "N-TRIPLE", jena.rdfcat.getCheckedLanguage( "N-TRIPLE" ) );
+        }
+
+    /**
+     * Test the identity transform - RDF/XML to RDF/XML
+     */
+    @Test
+    public void testRdfcatIdentity() {
+        Model source = ModelFactory.createDefaultModel();
+        source.read( "file:testing/cmd/rdfcat.xml", "RDF/XML" );
+
+        OutputStream so = new ByteArrayOutputStream();
+
+        rdfcatFixture rc = new rdfcatFixture( so );
+        rc.testGo( new String[] {"file:testing/cmd/rdfcat.xml"} );
+
+        Model output = asModel( so, "RDF/XML" );
+        assertTrue( output.isIsomorphicWith( source ));
+    }
+
+    /**
+     * Test the basic concatenation
+     */
+    @Test
+    public void testRdfcatConcat() {
+        Model source = ModelFactory.createDefaultModel();
+        source.read( "file:testing/cmd/rdfcat.xml", "RDF/XML" );
+
+        OutputStream so = new ByteArrayOutputStream();
+
+        rdfcatFixture rc = new rdfcatFixture( so );
+        rc.testGo( new String[] {"file:testing/cmd/rdfcat_1.xml", "file:testing/cmd/rdfcat_2.xml"} );
+
+        Model output = asModel( so, "RDF/XML" );
+        assertTrue( output.isIsomorphicWith( source ));
+    }
+
+    /**
+     * Change the default input language
+     */
+    @Test
+    public void testRdfcatConcat1() {
+        Model source = ModelFactory.createDefaultModel();
+        source.read( "file:testing/cmd/rdfcat.xml", "RDF/XML" );
+
+        OutputStream so = new ByteArrayOutputStream();
+
+        rdfcatFixture rc = new rdfcatFixture( so );
+        rc.testGo( new String[] {"-in", "N3", "file:testing/cmd/rdfcat_1_n3", "file:testing/cmd/rdfcat_2_n3"} );
+
+        Model output = asModel( so, "RDF/XML" );
+        assertTrue( output.isIsomorphicWith( source ));
+    }
+
+    @Test
+    public void testRdfcatN3ToRDFXML_0() {
+        doTestRdfcatOutput( "-n", "file:testing/cmd/rdfcat.n3", "RDF/XML", "RDF/XML" );
+    }
+
+    @Test
+    public void testRdfcatN3ToRDFXML_1() {
+        doTestRdfcatOutput( "-n3", "file:testing/cmd/rdfcat.n3", "RDF/XML", "RDF/XML" );
+    }
+
+    @Test
+    public void testRdfcatN3ToRDFXML_2() {
+        doTestRdfcatOutput( "-ttl", "file:testing/cmd/rdfcat.n3", "RDF/XML", "RDF/XML" );
+    }
+
+    @Test
+    public void testRdfcatN3ToRDFXML_3() {
+        doTestRdfcatOutput( "-N3", "file:testing/cmd/rdfcat.n3", "RDF/XML", "RDF/XML" );
+    }
+
+    @Test
+    public void testRdfcatN3ToNtriple() {
+        doTestRdfcatOutput( "-n", "file:testing/cmd/rdfcat.n3", "N-TRIPLE", "N-TRIPLE" );
+    }
+
+    @Test
+    public void testRdfcatN3ToN3() {
+        doTestRdfcatOutput( "-n", "file:testing/cmd/rdfcat.n3", "N3", "N3" );
+    }
+
+    @Test
+    public void testRdfcatN3ToRDFXMLDefault() {
+        doTestRdfcatOutput( null, "file:testing/cmd/rdfcat.n3", "RDF/XML", "RDF/XML" );
+    }
+
+
+    @Test
+    public void testRdfcatRDFXMLToRDFXML_0() {
+        doTestRdfcatOutput( "-x", "file:testing/cmd/rdfcat.xml", "RDF/XML", "RDF/XML" );
+    }
+
+    @Test
+    public void testRdfcatRDFXMLToRDFXML_1() {
+        doTestRdfcatOutput( "-xml", "file:testing/cmd/rdfcat.xml", "RDF/XML", "RDF/XML" );
+    }
+
+    @Test
+    public void testRdfcatRDFXMLToRDFXML_2() {
+        doTestRdfcatOutput( "-rdfxml", "file:testing/cmd/rdfcat.xml", "RDF/XML", "RDF/XML" );
+    }
+
+    @Test
+    public void testRdfcatRDFXMLToRDFXML_3() {
+        doTestRdfcatOutput( "-rdf", "file:testing/cmd/rdfcat.xml", "RDF/XML", "RDF/XML" );
+    }
+
+    @Test
+    public void testRdfcatRDFXMLToNtriple() {
+        doTestRdfcatOutput( "-x", "file:testing/cmd/rdfcat.xml", "N-TRIPLE", "N-TRIPLE" );
+    }
+
+    @Test
+    public void testRdfcatRDFXMLToN3() {
+        doTestRdfcatOutput( "-x", "file:testing/cmd/rdfcat.xml", "N3", "N3" );
+    }
+
+    @Test
+    public void testRdfcatRDFXMLToRDFXMLDefault() {
+        doTestRdfcatOutput( null, "file:testing/cmd/rdfcat.xml", "RDF/XML", "RDF/XML" );
+    }
+
+    @Test
+    public void testRdfcatNtripleToRDFXML_0() {
+        doTestRdfcatOutput( "-t", "file:testing/cmd/rdfcat.nt", "RDF/XML", "RDF/XML" );
+    }
+
+    @Test
+    public void testRdfcatNtripleToRDFXML_1() {
+        doTestRdfcatOutput( "-ntriple", "file:testing/cmd/rdfcat.nt", "RDF/XML", "RDF/XML" );
+    }
+
+    @Test
+    public void testRdfcatNtripleToRDFXML_2() {
+        doTestRdfcatOutput( "-ntriples", "file:testing/cmd/rdfcat.nt", "RDF/XML", "RDF/XML" );
+    }
+
+    @Test
+    public void testRdfcatNtripleToRDFXML_3() {
+        doTestRdfcatOutput( "-n-triple", "file:testing/cmd/rdfcat.nt", "RDF/XML", "RDF/XML" );
+    }
+
+    @Test
+    public void testRdfcatNtripleToNtriple() {
+        doTestRdfcatOutput( "-t", "file:testing/cmd/rdfcat.nt", "N-TRIPLE", "N-TRIPLE" );
+    }
+
+    @Test
+    public void testRdfcatNtripleToN3() {
+        doTestRdfcatOutput( "-t", "file:testing/cmd/rdfcat.nt", "N3", "N3" );
+    }
+
+    @Test
+    public void testRdfcatNtripleToRDFXMLDefault() {
+        doTestRdfcatOutput( null, "file:testing/cmd/rdfcat.nt", "RDF/XML", "RDF/XML" );
+    }
+
+    /**
+     * Utility to do a basic cat operation
+     */
+    public static void doTestRdfcatOutput( String inFormArg, String inputArg, String outFormArg, String parseAs ) {
+        Model source = ModelFactory.createDefaultModel();
+        source.read( "file:testing/cmd/rdfcat.xml" );
+
+        OutputStream so = new ByteArrayOutputStream();
+
+        rdfcatFixture rc = new rdfcatFixture( so );
+
+        List<String> l = new ArrayList<>();
+        if (outFormArg != null) {
+            l.add(  "-out" );
+            l.add(  outFormArg );
+        }
+        if (inFormArg != null) l.add( inFormArg );
+        l.add( inputArg );
+
+        String[] args = new String[l.size()];
+        for (int i = 0; i < l.size(); i++) {
+            args[i] = l.get(i);
+        }
+        // use file extension guessing
+        rc.testGo( args );
+
+        Model output = asModel( so, parseAs );
+        assertTrue( output.isIsomorphicWith( source ));
+    }
+
+    /** Convert an output stream holding a model content to a model */
+    protected static Model asModel( OutputStream so, String syntax ) {
+        String out = so.toString();
+        Model output = ModelFactory.createDefaultModel();
+        output.read( new StringReader( out ), "http://example.com/foo", syntax );
+        return output;
+    }
+
+    /**
+     * A minimal extension to rdfcat to provide a test fixture
+     */
+    protected static class rdfcatFixture
+        extends rdfcat
+    {
+        private OutputStream m_so;
+        protected rdfcatFixture( OutputStream so ) {
+            m_so = so;
+        }
+        @Override
+        protected OutputStream getOutputStream() {
+            return m_so;
+        }
+        protected void testGo( String[] args ) {
+            go( args );
+        }
+    }
+}