This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git

commit f39105563841733b7a97aaada5dd2f02adc21c40
Author: Andy Seaborne <[email protected]>
AuthorDate: Mon Nov 11 15:23:41 2024 +0000

    JENA-2837: Reduce use of model APIs in FusekiConfig
---
 .../jena/sparql/core/assembler/AssemblerUtils.java |  11 +-
 .../apache/jena/sparql/util/graph/GraphUtils.java  |   2 +-
 .../src/main/java/org/apache/jena/system/G.java    |  15 +-
 .../org/apache/jena/fuseki/build/BuildLib.java     | 201 ++++++------
 .../jena/fuseki/build/DatasetDescriptionMap.java   |  14 +-
 .../org/apache/jena/fuseki/build/FusekiConfig.java | 352 ++++++++++++---------
 .../build/{BuildLib.java => model/BuildLibM.java}  |  14 +-
 .../DatasetDescriptionMapM.java}                   |   6 +-
 .../FusekiConfigM.java}                            | 332 +++++++++----------
 .../org/apache/jena/fuseki/server/FusekiVocab.java |   3 +-
 .../apache/jena/fuseki/server/FusekiVocabG.java    | 111 +++++++
 .../org/apache/jena/fuseki/server/Operation.java   |  33 +-
 .../org/apache/jena/fuseki/main/FusekiServer.java  | 135 ++++----
 .../jena/fuseki/main/access/TestAuthorized.java    |  34 +-
 .../org/apache/jena/fuseki/mgt/ActionDatasets.java |   3 +-
 .../apache/jena/fuseki/webapp/FusekiWebapp.java    |   4 +-
 .../java/org/apache/jena/fuseki/TestBuilder.java   |  17 +-
 17 files changed, 731 insertions(+), 556 deletions(-)

diff --git 
a/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/AssemblerUtils.java
 
b/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/AssemblerUtils.java
index 7c4b2224c2..e67baddb97 100644
--- 
a/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/AssemblerUtils.java
+++ 
b/jena-arq/src/main/java/org/apache/jena/sparql/core/assembler/AssemblerUtils.java
@@ -108,13 +108,14 @@ public class AssemblerUtils
     }
 
     public static Model readAssemblerFile(String assemblerFile) {
-        Model spec = null ;
+        Model spec = null;
         try {
-            spec = RDFDataMgr.loadModel(assemblerFile) ;
-        } catch (Exception ex)
-        { throw new ARQException("Failed reading assembler description: 
"+ex.getMessage()) ; }
+            spec = RDFDataMgr.loadModel(assemblerFile);
+        } catch (Exception ex) {
+            throw new ARQException("Failed reading assembler description: " + 
ex.getMessage());
+        }
         addRegistered(spec);
-        return spec ;
+        return spec;
     }
 
     /** Add any extra information to the model.
diff --git 
a/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/GraphUtils.java 
b/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/GraphUtils.java
index 79daa39a15..cad5c3e69a 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/GraphUtils.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/GraphUtils.java
@@ -44,7 +44,7 @@ import org.apache.jena.util.iterator.ExtendedIterator;
 import org.apache.jena.util.iterator.NiceIterator;
 import org.apache.jena.vocabulary.RDF;
 
-/** Graph utilities. See also GraphFactory. */
+/** Graph utilities. */
 
 public class GraphUtils {
 
diff --git a/jena-arq/src/main/java/org/apache/jena/system/G.java 
b/jena-arq/src/main/java/org/apache/jena/system/G.java
index c18b46b7d5..547c19fc1b 100644
--- a/jena-arq/src/main/java/org/apache/jena/system/G.java
+++ b/jena-arq/src/main/java/org/apache/jena/system/G.java
@@ -41,10 +41,10 @@ import java.util.function.Supplier;
 import static org.apache.jena.graph.Node.ANY;
 
 /**
- * A library of functions for working with {@link Graph}. Internally all
+ * A library of functions for working with {@link Graph graphs}. Internally, 
all
  * {@link ExtendedIterator ExtendedIterators} used, run to completion or have
  * {@code .close()} called. Any {@link ExtendedIterator ExtendedIterators} 
returned
- * by functions in this library must be used in the same way
+ * by functions in this library must be used in the same way.
  */
 public class G {
     private G() {}
@@ -93,6 +93,12 @@ public class G {
         return hasDatatype(n, XSDDatatype.XSDboolean);
     }
 
+    public static boolean asBoolean(Node n)     {
+        if ( ! isBoolean(n) )
+            throw new RDFDataException("Not a boolean: "+NodeFmtLib.strTTL(n));
+        return Boolean.TRUE.equals(n.getLiteralValue());
+    }
+
     /**
      * Convert null to Node.ANY, otherwise return the original node so that
      * {@code ==} may be used to test whether any change has occurred.
@@ -267,7 +273,6 @@ public class G {
      */
     public static boolean hasOnePO(Graph graph, Node predicate, Node object) {
         Objects.requireNonNull(graph, "graph");
-        // Not contains!
         return findUniqueTriple(graph, Node.ANY, predicate, object) != null;
     }
 
@@ -325,8 +330,6 @@ public class G {
         return findZeroOneQuad(dsg, graph, subject, predicate, object);
     }
 
-    // ---- Multiple matches.
-
     /**
      * Get triple if there is exactly one to match the s/p/o; else return null
      * if none or more than one.
@@ -336,6 +339,8 @@ public class G {
         return findQuadOrNull(dsg, graph, subject, predicate, object);
     }
 
+    // ---- Multiple matches.
+
     /**
      * {@link ExtendedIterator} of objects where the triple matches for 
subject and
      * predicate (which can be wildcards). The {@link ExtendedIterator} must 
be fully
diff --git 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/BuildLib.java
 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/BuildLib.java
index 302496b0b6..e54000bb62 100644
--- 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/BuildLib.java
+++ 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/BuildLib.java
@@ -19,7 +19,6 @@
 package org.apache.jena.fuseki.build;
 
 import static org.apache.jena.fuseki.build.FusekiPrefixes.PREFIXES;
-import static org.apache.jena.riot.out.NodeFmtLib.displayStr;
 
 import java.lang.reflect.Constructor;
 import java.net.URL;
@@ -34,11 +33,24 @@ import org.apache.jena.fuseki.Fuseki;
 import org.apache.jena.fuseki.FusekiConfigException;
 import org.apache.jena.fuseki.server.Operation;
 import org.apache.jena.fuseki.servlets.ActionService;
+import org.apache.jena.graph.Graph;
+import org.apache.jena.graph.Node;
 import org.apache.jena.graph.NodeFactory;
-import org.apache.jena.query.*;
-import org.apache.jena.rdf.model.*;
+import org.apache.jena.query.Query;
+import org.apache.jena.query.QueryFactory;
+import org.apache.jena.riot.out.NodeFmtLib;
+import org.apache.jena.riot.system.PrefixMap;
+import org.apache.jena.riot.system.Prefixes;
 import org.apache.jena.shared.JenaException;
-import org.apache.jena.shared.PrefixMapping;
+import org.apache.jena.sparql.core.Var;
+import org.apache.jena.sparql.engine.binding.Binding;
+import org.apache.jena.sparql.engine.binding.BindingFactory;
+import org.apache.jena.sparql.exec.QueryExec;
+import org.apache.jena.sparql.exec.QueryExecBuilder;
+import org.apache.jena.sparql.exec.RowSet;
+import org.apache.jena.sparql.util.graph.GNode;
+import org.apache.jena.sparql.util.graph.GraphList;
+import org.apache.jena.system.G;
 import org.apache.jena.vocabulary.RDFS;
 
 /**
@@ -48,72 +60,39 @@ import org.apache.jena.vocabulary.RDFS;
 
     private BuildLib() {}
 
-    // ---- Helper code
-    /*package*/ static ResultSet query(String string, Model m) {
-        return query(string, m, null, null);
+    /*package*/ static RowSet query(String string, Graph graph) {
+        return query(string, graph, null, null);
     }
 
-    /*package*/ static RDFNode queryOne(String string, Model m, String 
varname) {
-        ResultSet rs = query(string, m);
-        return getExactlyOne(rs, varname);
-    }
-
-    private static RDFNode getExactlyOne(ResultSet rs, String varname) {
-        if ( ! rs.hasNext() )
-            return null;
-        QuerySolution qs = rs.next();
-        if ( rs.hasNext() )
-            return null;
-        return qs.get(varname);
-    }
-
-    /*package*/ static ResultSet query(String string, Dataset ds) {
-        return query(string, ds, null, null);
-    }
-
-    /*package*/ static ResultSet query(String string, Model m, String varName, 
RDFNode value) {
-        Query query = QueryFactory.create(PREFIXES + string);
-        QuerySolutionMap initValues = null;
-        if ( varName != null && value != null )
-            initValues = querySolution(varName, value);
-        try ( QueryExecution qExec = 
QueryExecution.create().query(query).model(m).initialBinding(initValues).build()
 ) {
-            return ResultSetFactory.copyResults(qExec.execSelect());
-        }
-    }
-
-    /*package*/ static ResultSet query(String string, Dataset ds, String 
varName, RDFNode value) {
+    /*package*/ static RowSet query(String string, Graph graph, String 
varName, Node value) {
         Query query = QueryFactory.create(PREFIXES + string);
-        QuerySolutionMap initValues = null;
+        QueryExecBuilder qExec = QueryExec.graph(graph).query(query);
         if ( varName != null && value != null )
-            initValues = querySolution(varName, value);
-        try ( QueryExecution qExec = QueryExecution
-                    .dataset(ds)
-                    .query(query)
-                    .substitution(initValues)
-                    .build() ) {
-            return ResultSetFactory.copyResults(qExec.execSelect());
-        }
+            qExec.substitution(varName, value);
+        return qExec.build().select().materialize();
     }
 
-    private static QuerySolutionMap querySolution(String varName, RDFNode 
value) {
-        QuerySolutionMap qsm = new QuerySolutionMap();
-        querySolution(qsm, varName, value);
-        return qsm;
+    private static Binding querySubstitution(String varName, Node value) {
+        Var var = Var.alloc(varName);
+        return BindingFactory.binding(var, value);
     }
 
-    /*package*/ static QuerySolutionMap querySolution(QuerySolutionMap qsm, 
String varName, RDFNode value) {
-        qsm.add(varName, value);
-        return qsm;
+    /*package*/ static Node getOne(Graph graph, Node subject, Node property) {
+        List<Node> x = G.listSP(graph, subject, property);
+        if ( x.isEmpty() )
+            throw new FusekiConfigException("No property '" + 
BuildLib.displayStr(graph, property) + "' for service " + 
BuildLib.displayStr(graph, subject));
+        if ( x.size() > 1 )
+            throw new FusekiConfigException("Multiple properties '" + 
BuildLib.displayStr(graph, property) + "' for service " + 
BuildLib.displayStr(graph, subject));
+        return x.get(0);
     }
 
-    /*package*/ static RDFNode getOne(Resource svc, Property property) {
-        ResultSet rs = BuildLib.query("SELECT * { ?svc <" + property.getURI() 
+ "> ?x}", svc.getModel(), "svc", svc);
-        if ( !rs.hasNext() )
-            throw new FusekiConfigException("No property '" + property + "' 
for service " + BuildLib.nodeLabel(svc));
-        RDFNode x = rs.next().get("x");
-        if ( rs.hasNext() )
-            throw new FusekiConfigException("Multiple properties '" + property 
+ "' for service " + BuildLib.nodeLabel(svc));
-        return x;
+    /*package*/ static Node getZeroOrOne(Graph graph, Node subject, Node 
property) {
+        List<Node> x = G.listSP(graph, subject, property);
+        if ( x.isEmpty() )
+            return null;
+        if ( x.size() > 1 )
+            throw new FusekiConfigException("Multiple triples for 
"+displayStr(graph, subject)+" "+displayStr(graph, property));
+        return x.get(0);
     }
 
     /**
@@ -121,84 +100,80 @@ import org.apache.jena.vocabulary.RDFS;
      * mixture. If the subject/property isn't present, return null, so a 
caller can tell
      * the difference between "not present" and an empty list value.
      */
-    /*package*/ static Collection<RDFNode> getAll(Resource resource, String 
property) {
-        ResultSet rs = BuildLib.query("SELECT * { ?subject " + property + " 
?x}", resource.getModel(), "subject", resource);
-        if ( ! rs.hasNext() )
+    /*package*/ static Collection<Node> getMultiple(Graph graph, Node 
resource, Node property) {
+        List<Node> nodes = G.listSP(graph, resource, property);
+        if ( nodes.isEmpty() )
             return null;
-        List<RDFNode> results = new ArrayList<>();
-        rs.forEachRemaining(qs->{
-            RDFNode n = qs.get("x");
-            try {
-                RDFList list = n.as(RDFList.class);
-                results.addAll(list.asJavaList());
-            } catch (JenaException x) {
-                // Not a list.
-                results.add(n);
-            }
+        // For mall lists (one level) - expand by members.
+        List<Node> results = new ArrayList<>();
+
+        nodes.forEach(node->{
+            List<Node> members = listMembers(graph, node);
+            if ( members != null )
+                results.addAll(members);
+            else
+                results.add(node);
         });
         return results;
     }
 
+    private static List<Node> listMembers(Graph graph, Node node) {
+        GNode gnode = new GNode(graph, node);
+        if ( ! GraphList.isListNode(gnode) )
+            return null;
+        List<Node> list = GraphList.members(gnode);
+        return list;
+    }
+
     // Node presentation
-    /*package*/ static String nodeLabel(RDFNode n) {
+
+    /*package*/ static String displayStr(Graph graph, Node n) {
         if ( n == null )
-            return "<null>";
-        if ( n instanceof Resource r)
-            return strForResource(r);
+            return "NULL";
+        if ( graph == null )
+            return NodeFmtLib.str(n, null);
 
-        Literal lit = (Literal)n;
-        return lit.getLexicalForm();
+        PrefixMap prefixMap = Prefixes.adapt(graph);
+        return NodeFmtLib.str(n, null, prefixMap);
     }
 
-    /*package*/ static String strForResource(Resource r) {
-        return strForResource(r, r.getModel());
-    }
+    /*package*/ static String strForResource(Graph graph, Node node) {
+        if ( node == null )
+            return "NULL";
+        if ( G.hasProperty(graph, node, RDFS.Nodes.label) ) {
 
-    /*package*/ static String strForResource(Resource r, PrefixMapping pm) {
-        if ( r == null )
-            return "NULL ";
-        if ( r.hasProperty(RDFS.label) ) {
-            RDFNode n = r.getProperty(RDFS.label).getObject();
-            if ( n instanceof Literal literal )
-                return literal.getString();
+            Node label = G.getOneSP(graph, node, RDFS.Nodes.label);
+            if ( label.isLiteral() )
+                return label.getLiteralLexicalForm();
         }
 
-        if ( r.isAnon() )
+        if ( node.isBlank() )
             return "<<blank node>>";
 
-        if ( pm == null )
-            pm = r.getModel();
-
-        return strForURI(r.getURI(), pm);
+        if ( node.isURI() )
+            return strForURI(graph, node.getURI());
+        throw notSupported(node);
     }
 
-    /*package*/ static String strForURI(String uri, PrefixMapping pm) {
-        if ( pm != null ) {
-            String x = pm.shortForm(uri);
+    private static RuntimeException notSupported(Node node) {
+        return new JenaException("Not supported: "+node);
+    }
 
-            if ( !x.equals(uri) )
+    /*package*/ static String strForURI(Graph graph, String uri) {
+        if ( graph != null ) {
+            PrefixMap prefixMap = Prefixes.adapt(graph);
+            String x = graph.getPrefixMapping().qnameFor(uri);
+            if ( x != null )
                 return x;
         }
         return "<" + uri + ">";
     }
 
-    /*package*/ static RDFNode getZeroOrOne(Resource ep, Property property) {
-        StmtIterator iter = ep.listProperties(property);
-        try {
-            if ( ! iter.hasNext() )
-                return null;
-            RDFNode x = iter.next().getObject();
-            if ( iter.hasNext() )
-                throw new FusekiConfigException("Multiple triples for 
"+displayStr(ep)+" "+displayStr(property));
-            return x;
-        } finally { iter.close(); }
-    }
-
     /** Load a class (an {@link ActionService}) and create an {@link 
Operation} for it. */
-    /*package*/ static Pair<Operation, ActionService> 
loadOperationActionService(RDFNode implementation) {
+    /*package*/ static Pair<Operation, ActionService> 
loadOperationActionService(Graph graph, Node implementation) {
         String classURI = implementation.isLiteral()
-            ? implementation.asLiteral().getLexicalForm()
-            : ((Resource)implementation).getURI();
+            ? implementation.getLiteralLexicalForm()
+            : implementation.getURI();
         String javaScheme = "java:";
         String fileScheme = "file:";
         String scheme = null;
diff --git 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/DatasetDescriptionMap.java
 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/DatasetDescriptionMap.java
index 647aa94959..c4bf383066 100644
--- 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/DatasetDescriptionMap.java
+++ 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/DatasetDescriptionMap.java
@@ -22,8 +22,8 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.jena.atlas.logging.Log;
-import org.apache.jena.query.Dataset;
-import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.graph.Node;
+import org.apache.jena.sparql.core.DatasetGraph;
 
 /**
  * Record of datasets created from descriptions.
@@ -33,20 +33,20 @@ import org.apache.jena.rdf.model.Resource;
  * corresponds to one dataset object when multiple services refer to the
  * same dataset.
  */
-public class DatasetDescriptionMap  {
+public class DatasetDescriptionMap {
 
-       private Map<Resource, Dataset> map = new HashMap<>();
+       private Map<Node, DatasetGraph> map = new HashMap<>();
 
        public DatasetDescriptionMap() {}
 
-    public void register(Resource node, Dataset ds) {
-        Dataset dsCurrent = map.get(node);
+    public void register(Node node, DatasetGraph ds) {
+        DatasetGraph dsCurrent = map.get(node);
         if ( dsCurrent != null && ! dsCurrent.equals(ds) )
             Log.warn(this.getClass(), "Replacing registered dataset for 
"+node);
         map.put(node, ds);
     }
 
-    public Dataset get(Resource node) {
+    public DatasetGraph get(Node node) {
         return map.get(node);
     }
 
diff --git 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
index cacbb712b0..db6de6c5de 100644
--- 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
+++ 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
@@ -21,10 +21,11 @@ package org.apache.jena.fuseki.build;
 import static java.lang.String.format;
 import static java.util.stream.Collectors.toList;
 import static org.apache.jena.fuseki.build.BuildLib.getZeroOrOne;
-import static org.apache.jena.fuseki.build.BuildLib.nodeLabel;
-import static org.apache.jena.fuseki.server.FusekiVocab.*;
+import static org.apache.jena.fuseki.server.FusekiVocabG.*;
+import static org.apache.jena.fuseki.build.BuildLib.displayStr;
 import static org.apache.jena.riot.RDFLanguages.filenameToLang;
 import static org.apache.jena.riot.RDFParserRegistry.isRegistered;
+import static org.apache.jena.system.G.isResource;
 
 import java.io.File;
 import java.io.IOException;
@@ -39,7 +40,6 @@ import org.apache.jena.assembler.Assembler;
 import org.apache.jena.assembler.JA;
 import org.apache.jena.atlas.lib.IRILib;
 import org.apache.jena.atlas.lib.Pair;
-import org.apache.jena.datatypes.xsd.XSDDatatype;
 import org.apache.jena.fuseki.Fuseki;
 import org.apache.jena.fuseki.FusekiConfigException;
 import org.apache.jena.fuseki.FusekiException;
@@ -48,10 +48,10 @@ import org.apache.jena.fuseki.auth.AuthPolicy;
 import org.apache.jena.fuseki.auth.AuthPolicyList;
 import org.apache.jena.fuseki.server.*;
 import org.apache.jena.fuseki.servlets.ActionService;
+import org.apache.jena.graph.Graph;
 import org.apache.jena.graph.Node;
 import org.apache.jena.query.Dataset;
-import org.apache.jena.query.QuerySolution;
-import org.apache.jena.query.ResultSet;
+import org.apache.jena.query.DatasetFactory;
 import org.apache.jena.rdf.model.*;
 import org.apache.jena.rdf.model.impl.Util;
 import org.apache.jena.riot.Lang;
@@ -59,9 +59,10 @@ import org.apache.jena.shared.JenaException;
 import org.apache.jena.sparql.core.DatasetGraph;
 import org.apache.jena.sparql.core.assembler.AssemblerUtils;
 import org.apache.jena.sparql.core.assembler.NamedDatasetAssembler;
+import org.apache.jena.sparql.engine.binding.Binding;
+import org.apache.jena.sparql.exec.RowSet;
 import org.apache.jena.sparql.util.Context;
-import org.apache.jena.sparql.util.FmtUtils;
-import org.apache.jena.sparql.util.graph.GraphUtils;
+import org.apache.jena.system.G;
 import org.apache.jena.vocabulary.RDF;
 import org.slf4j.Logger;
 
@@ -112,22 +113,22 @@ public class FusekiConfig {
         return dataServiceBuilder;
     }
 
-    public static void addDataService(DataAccessPointRegistry 
dataAccessPoints, String name, DataService dataService) {
-        name = DataAccessPoint.canonical(name);
-        if ( dataAccessPoints.isRegistered(name) )
-            throw new FusekiConfigException("Data service name already 
registered: "+name);
-        DataAccessPoint dap = new DataAccessPoint(name, dataService);
-        dataAccessPoints.register(dap);
-    }
-
-    public static void addDataset(DataAccessPointRegistry dataAccessPoints, 
String name, DatasetGraph dsg, boolean withUpdate) {
-        name = DataAccessPoint.canonical(name);
-        if ( dataAccessPoints.isRegistered(name) )
-            throw new FusekiConfigException("Data service name already 
registered: "+name);
-        DataService dataService = buildDataServiceStd(dsg, withUpdate);
-        DataAccessPoint dap = new DataAccessPoint(name, dataService);
-        dataAccessPoints.register(dap);
-    }
+//    private static void addDataService(DataAccessPointRegistry 
dataAccessPoints, String name, DataService dataService) {
+//        name = DataAccessPoint.canonical(name);
+//        if ( dataAccessPoints.isRegistered(name) )
+//            throw new FusekiConfigException("Data service name already 
registered: "+name);
+//        DataAccessPoint dap = new DataAccessPoint(name, dataService);
+//        dataAccessPoints.register(dap);
+//    }
+//
+//    public static void addDataset(DataAccessPointRegistry dataAccessPoints, 
String name, DatasetGraph dsg, boolean withUpdate) {
+//        name = DataAccessPoint.canonical(name);
+//        if ( dataAccessPoints.isRegistered(name) )
+//            throw new FusekiConfigException("Data service name already 
registered: "+name);
+//        DataService dataService = buildDataServiceStd(dsg, withUpdate);
+//        DataAccessPoint dap = new DataAccessPoint(name, dataService);
+//        dataAccessPoints.register(dap);
+//    }
 
     public static DataService buildDataServiceStd(DatasetGraph dsg, boolean 
withUpdate) {
         return DataService.newBuilder(dsg)
@@ -140,21 +141,25 @@ public class FusekiConfig {
         dataAccessPoints.remove(name);
     }
 
+    @Deprecated
+    public static AuthPolicy allowedUsers(Resource server) {
+        return allowedUsers(server.getModel().getGraph(), server.asNode());
+    }
+
     /** Get the allowed users on a resource.
      *  Returns null if the resource is null or if there were no settings.
      *
      * @return RequestAuthorization
      */
-    public static AuthPolicy allowedUsers(Resource resource) {
+    public static AuthPolicy allowedUsers(Graph graph, Node resource) {
         if ( resource == null )
             return null;
-        Collection<RDFNode> allowedUsers = BuildLib.getAll(resource, 
"fu:"+pAllowedUsers.getLocalName());
+        Collection<Node> allowedUsers = BuildLib.getMultiple(graph, resource, 
pAllowedUsers);
         if ( allowedUsers == null )
             // Indicate no settings.
             return null;
         // Check all values are simple strings
         List<String> bad = allowedUsers.stream()
-            .map(RDFNode::asNode)
             .filter(rn -> ! Util.isSimpleString(rn))
             .map(rn->rn.toString())
             .collect(toList());
@@ -164,14 +169,13 @@ public class FusekiConfig {
         }
         // RDFNodes/literals to strings.
         Collection<String> userNames = allowedUsers.stream()
-            .map(RDFNode::asNode)
             .map(Node::getLiteralLexicalForm)
             .collect(toList());
         return Auth.policyAllowSpecific(userNames);
     }
 
     /**
-     * Process a configuration file and return the {@link DataAccessPoint 
DataAccessPoints};
+     * Process a configuration and return the {@link DataAccessPoint 
DataAccessPoints};
      * set the context provided for server-wide settings.
      *
      * This bundles together the steps:
@@ -182,22 +186,57 @@ public class FusekiConfig {
      * <li>{@link #servicesAndDatasets}
      * </ul>
      */
-    public static List<DataAccessPoint> processServerConfiguration(Model 
configuration, Context context) {
-        Resource server = findServer(configuration);
+    public static List<DataAccessPoint> processServerConfiguration(Graph 
configuration, Context context) {
+        Node server = findServer(configuration);
         if ( server != null ) {
-            mergeContext(server, context);
-            processLoadClass(server);
+            // XXX Temporary
+            Resource rServer = resource(configuration, server);
+            mergeContext(configuration,server, context);
+            processLoadClass(configuration,server);
         }
         // Process services, whether via server ja:services or, if absent, by 
finding by type.
-        return servicesAndDatasets$(server, configuration);
+        return servicesAndDatasets$(configuration, server);
+    }
+
+    /**
+     * Process a configuration and return the {@link DataAccessPoint 
DataAccessPoints};
+     * set the context provided for server-wide settings.
+     *
+     * This bundles together the steps:
+     * <ul>
+     * <li>{@link #findServer}
+     * <li>{@link #parseContext}
+     * <li>{@link #processLoadClass} (legacy)
+     * <li>{@link #servicesAndDatasets}
+     * </ul>
+     */
+    public static List<DataAccessPoint> processServerConfiguration(Model 
configuration, Context context) {
+        return processServerConfiguration(configuration.getGraph(), context);
+    }
+
+    // XXX Adapter
+    /*package*/ static Resource resource(Graph graph, Node node) {
+        Model m = ModelFactory.createModelForGraph(graph);
+        RDFNode rNode = m.asRDFNode(node);
+        if ( ! rNode.isResource() )
+            throw new FusekiConfigException("Not a resource: "+node);
+        return rNode.asResource();
+    }
+
+    @Deprecated
+    public static Resource findServer(Model model) {
+        Node server = findServer(model.getGraph());
+        if ( server == null )
+            return null;
+        return resource(model.getGraph(), server);
     }
 
     /* Find the server resource in a configuration file.
      * Returns null if there isn't one.
      * Raises {@link FusekiConfigException} is there are more than one.
      */
-    public static Resource findServer(Model model) {
-        List<Resource> servers = GraphUtils.listResourcesByType(model, 
FusekiVocab.tServer);
+    public static Node findServer(Graph graph) {
+        List<Node> servers = G.nodesOfTypeAsList(graph, FusekiVocabG.tServer);
         if ( servers.size() == 0 )
             // "No server" is fine.
             return null;
@@ -205,7 +244,7 @@ public class FusekiConfig {
             throw new FusekiConfigException(servers.size()
                                             + " servers found (must be exactly 
one in a configuration file)");
         // ---- Server
-        Resource server = servers.get(0);
+        Node server = servers.get(0);
         return server;
     }
 
@@ -213,48 +252,51 @@ public class FusekiConfig {
      * Process the resource for {@link Context} settings.
      * Return a new {@link Context}
      */
-    private static Context parseContext(Resource resource) {
+    private static Context parseContext(Graph configuration, Node resource) {
         if ( resource == null )
             return null;
-        return AssemblerUtils.parseContext(resource);
+        Resource r = resource(configuration, resource);
+        return AssemblerUtils.parseContext(r);
     }
 
     /**
      * Process the resource for {@link Context} settings
      * and update an existing {@link Context}.
      */
-    private static void mergeContext(Resource resource, Context context) {
+    private static void mergeContext(Graph configuration, Node resource, 
Context context) {
         if ( resource == null )
             return ;
-        AssemblerUtils.mergeContext(resource, context);
+        Resource r = resource(configuration, resource);
+        AssemblerUtils.mergeContext(r, context);
     }
 
     /**
      * Process any {@code ja:loadClass}
      */
-    public static void processLoadClass(Resource server) {
+    public static void processLoadClass(Graph configuration, Node server) {
         if ( server == null )
             return;
-        StmtIterator sIter = server.listProperties(JA.loadClass);
-        for (; sIter.hasNext(); ) {
-            Statement s = sIter.nextStatement();
-            RDFNode rn = s.getObject();
+        List<Node> x = G.listSP(configuration, server, JA.loadClass.asNode());
+
+        for ( Node rn : x ) {
             String className = null;
-            if ( rn instanceof Resource res ) {
-                String uri = res.getURI();
-                if ( uri == null ) {
-                    log.warn("Blank node for class to load");
-                    continue;
-                }
+            if ( rn.isBlank() ) {
+                log.warn("Blank node for class to load");
+                continue;
+            }
+            if ( rn.isURI() ) {
+                String uri = rn.getURI();
                 String javaScheme = "java:";
                 if ( !uri.startsWith(javaScheme) ) {
                     log.warn("Class to load is not 'java:': " + uri);
                     continue;
                 }
                 className = uri.substring(javaScheme.length());
-            }
-            if ( rn instanceof Literal lit)
-                className = lit.getLexicalForm();
+            } else if ( G.isString(rn) )
+                className = rn.getLiteralLexicalForm();
+
+            if ( className == null )
+                throw new FusekiConfigException("Not a class name: 
"+displayStr(configuration, rn));
             loadAndInit(className);
         }
     }
@@ -264,40 +306,39 @@ public class FusekiConfig {
      * It looks {@code fuseki:services ( .... )} then, if not found, all 
{@code rtdf:type fuseki:services}.
      * @see #processServerConfiguration
      */
-    public static List<DataAccessPoint> servicesAndDatasets(Model model) {
-        Resource server = findServer(model);
-        return servicesAndDatasets$(server, model);
+    public static List<DataAccessPoint> servicesAndDatasets(Graph graph) {
+        Node server = findServer(graph);
+        return servicesAndDatasets$(graph, server);
     }
 
-    /** Find and process datasets and services in a configuration file
-     * starting from {@code server} which can have a {@code fuseki:services ( 
.... )}
-     * but, if not found, all {@code rdf:type fuseki:services} are processed.
-     */
-    private
-    /*public*/ static List<DataAccessPoint> 
servicesAndDatasets_notUsed(Resource server) {
-        Objects.requireNonNull(server);
-        return servicesAndDatasets$(server, server.getModel());
+    @Deprecated
+    public static List<DataAccessPoint> servicesAndDatasets(Model model) {
+        return servicesAndDatasets(model.getGraph());
     }
 
-    private static List<DataAccessPoint> servicesAndDatasets$(Resource server, 
Model model) {
+    private static List<DataAccessPoint> servicesAndDatasets$(Graph 
configuration, Node server) {
         DatasetDescriptionMap dsDescMap = new DatasetDescriptionMap();
         NamedDatasetAssembler.sharedDatasetPool.clear();
         // ---- Services
         // Server to services.
-        ResultSet rs = BuildLib.query("SELECT * { ?s fu:services [ list:member 
?service ] }", model, "s", server);
+        RowSet rs = BuildLib.query("SELECT * { ?s fu:services [ list:member 
?service ] }", configuration, "s", server);
+
+        List<Node> services = rs.stream().map(b->b.get("service")).toList();
+
         List<DataAccessPoint> accessPoints = new ArrayList<>();
 
         // If none, look for services by type.
         if ( ! rs.hasNext() )
             // No "fu:services ( .... )" so try looking for services directly.
             // This means Fuseki2, service configuration files (no server 
section) work for --conf.
-            rs = BuildLib.query("SELECT ?service { ?service a fu:Service }", 
model);
+            rs = BuildLib.query("SELECT ?service { ?service a fu:Service }", 
configuration);
 
         // rs is a result set of services to process.
         for (; rs.hasNext(); ) {
-            QuerySolution soln = rs.next();
-            Resource svc = soln.getResource("service");
-            DataAccessPoint acc = buildDataAccessPoint(svc, dsDescMap);
+            Binding soln = rs.next();
+            Node svc = soln.get("service");
+
+            DataAccessPoint acc = buildDataAccessPoint(configuration, svc, 
dsDescMap);
             if ( acc != null )
                 accessPoints.add(acc);
         }
@@ -350,7 +391,7 @@ public class FusekiConfig {
                 DatasetDescriptionMap dsDescMap = new DatasetDescriptionMap();
                 String fn = IRILib.filenameToIRI(p.toString());
                 log.info("Load configuration: "+fn);
-                Model m = readAssemblerFile(fn);
+                Graph m = readAssemblerFile(fn).getGraph();
                 readConfiguration(m, dsDescMap, dataServiceRef);
             }
         } catch (IOException ex) {
@@ -359,53 +400,57 @@ public class FusekiConfig {
         return dataServiceRef;
     }
 
-    /** Read a configuration in a model.
+    /**
+     * Read a configuration in a model.
      * Allow dataset descriptions to be carried over from another place.
      * Add to a list.
      */
-    private static void readConfiguration(Model m, DatasetDescriptionMap 
dsDescMap, List<DataAccessPoint> dataServiceRef) {
-        List<Resource> services = GraphUtils.listResourcesByType(m, 
FusekiVocab.fusekiService);
+    private static void readConfiguration(Graph configuration, 
DatasetDescriptionMap dsDescMap, List<DataAccessPoint> dataServiceRef) {
+        List<Node> services = G.nodesOfTypeAsList(configuration, 
FusekiVocabG.fusekiService);
 
         if ( services.size() == 0 ) {
             log.error("No services found");
             throw new FusekiConfigException();
         }
 
-        for ( Resource service : services ) {
-            DataAccessPoint acc = buildDataAccessPoint(service, dsDescMap);
+        for ( Node service : services ) {
+            DataAccessPoint acc = buildDataAccessPoint(configuration,service, 
dsDescMap);
             if ( acc != null )
                 dataServiceRef.add(acc);
         }
     }
 
-    /** Build a DataAccessPoint, including DataService, from the description 
at Resource svc */
+    @Deprecated
     public static DataAccessPoint buildDataAccessPoint(Resource svc, 
DatasetDescriptionMap dsDescMap) {
-        RDFNode n = BuildLib.getOne(svc, FusekiVocab.pServiceName);
+        return buildDataAccessPoint(svc.getModel().getGraph(), svc.asNode(), 
dsDescMap);
+    }
+
+    /** Build a DataAccessPoint, including DataService, from the description 
at Resource svc */
+    public static DataAccessPoint buildDataAccessPoint(Graph configuration, 
Node fusekiService, DatasetDescriptionMap dsDescMap) {
+        Node n = BuildLib.getOne(configuration, fusekiService, 
FusekiVocabG.pServiceName);
         try {
             if ( ! n.isLiteral() )
-                throw new FusekiConfigException("Not a literal for access 
point name: "+FmtUtils.stringForRDFNode(n));
-            Literal object = n.asLiteral();
-
-            if ( object.getDatatype() != null && ! 
object.getDatatype().equals(XSDDatatype.XSDstring) )
-                Fuseki.configLog.error(format("Service name '%s' is not a 
string", FmtUtils.stringForRDFNode(object)));
+                throw new FusekiConfigException("Not a literal for access 
point name: "+BuildLib.displayStr(configuration, n));
+            if ( ! Util.isSimpleString(n) )
+                Fuseki.configLog.error(format("Service name '%s' is not a 
string", BuildLib.strForResource(configuration, n)));
 
-            String name = object.getLexicalForm();
+            String name = n.getLiteralLexicalForm();
             name = DataAccessPoint.canonical(name);
-            AuthPolicy allowedUsers = allowedUsers(svc);
-            DataService dataService = buildDataService(svc, 
dsDescMap).setAuthPolicy(allowedUsers).build();
+            AuthPolicy allowedUsers = allowedUsers(configuration, 
fusekiService);
+            DataService dataService = buildDataService(configuration, 
fusekiService, dsDescMap).setAuthPolicy(allowedUsers).build();
             DataAccessPoint dataAccess = new DataAccessPoint(name, 
dataService);
             return dataAccess;
         } catch (FusekiException ex) {
-            Fuseki.configLog.error("Skipping: Failed to build service for 
"+FmtUtils.stringForRDFNode(n));
+            Fuseki.configLog.error("Skipping: Failed to build service for 
"+BuildLib.displayStr(configuration, n));
             Fuseki.configLog.error("    "+ex.getMessage());
             return null;
         }
     }
 
-    private static DataService.Builder buildDataService(Resource 
fusekiService, DatasetDescriptionMap dsDescMap) {
-        Resource datasetDesc = (Resource)BuildLib.getOne(fusekiService, 
FusekiVocab.pDataset);
-        Dataset ds = getDataset(datasetDesc, dsDescMap);
-        DataService.Builder dataService = 
DataService.newBuilder(ds.asDatasetGraph());
+    private static DataService.Builder buildDataService(Graph configuration, 
Node fusekiService, DatasetDescriptionMap dsDescMap) {
+        Node datasetDesc = BuildLib.getOne(configuration, fusekiService, 
FusekiVocabG.pDataset);
+        DatasetGraph dsg = getDataset(configuration, datasetDesc, dsDescMap);
+        DataService.Builder dataService = DataService.newBuilder(dsg);
         Set<Endpoint> endpoints1 = new HashSet<>();
         Set<Endpoint> endpoints2 = new HashSet<>();
 
@@ -413,11 +458,11 @@ public class FusekiConfig {
         //    fuseki:serviceQuery "sparql";
         //or
         //    fuseki:serviceQuery [ fuseki:name "sparql" ; fuseki:allowedUsers 
(..) ];
-        accEndpointOldStyle(endpoints1, Operation.Query,    fusekiService,  
pServiceQueryEP);
-        accEndpointOldStyle(endpoints1, Operation.Update,   fusekiService,  
pServiceUpdateEP);
-        //accEndpointOldStyle(endpoints1, Operation.Upload,   fusekiService,  
pServiceUploadEP);
-        accEndpointOldStyle(endpoints1, Operation.GSP_R,    fusekiService,  
pServiceReadGraphStoreEP);
-        accEndpointOldStyle(endpoints1, Operation.GSP_RW,   fusekiService,  
pServiceReadWriteGraphStoreEP);
+        accEndpointOldStyle(endpoints1, Operation.Query,    configuration, 
fusekiService,  pServiceQueryEP);
+        accEndpointOldStyle(endpoints1, Operation.Update,   configuration, 
fusekiService,  pServiceUpdateEP);
+        //accEndpointOldStyle(endpoints1, Operation.Upload,   configuration, 
fusekiService,  pServiceUploadEP);
+        accEndpointOldStyle(endpoints1, Operation.GSP_R,    configuration, 
fusekiService,  pServiceReadGraphStoreEP);
+        accEndpointOldStyle(endpoints1, Operation.GSP_RW,   configuration, 
fusekiService,  pServiceReadWriteGraphStoreEP);
 
         // ---- Legacy for old style: a request would also try the dataset 
(i.e. no endpoint name).
         // If "sparql" then allow /dataset?query=
@@ -435,7 +480,7 @@ public class FusekiConfig {
         //   fuseki:endpoint [ fuseki:operation fuseki:query ; fuseki:name "" 
; fuseki:allowedUsers (....) ] ;
         //   and more.
 
-        accFusekiEndpoints(endpoints2, fusekiService, dsDescMap);
+        accFusekiEndpoints(endpoints2, configuration, fusekiService, 
dsDescMap);
         // This will overwrite old style entries of the same fuseki:name.
         endpoints2.forEach(dataService::addEndpoint);
 
@@ -477,12 +522,12 @@ public class FusekiConfig {
 
     /** Find and parse {@code fuseki:endpoint} descriptions. */
     private
-    static void accFusekiEndpoints(Set<Endpoint> endpoints, Resource 
fusekiService, DatasetDescriptionMap dsDescMap) {
-        StmtIterator endpointsDesc = fusekiService.listProperties(pEndpoint);
-        endpointsDesc.forEachRemaining(ep-> {
-            if ( ! ep.getObject().isResource() )
-                throw new FusekiConfigException("Literal for fuseki:endpoint: 
expected blank node or resource: "+FmtUtils.stringForRDFNode(fusekiService));
-            Endpoint endpoint = buildEndpoint(fusekiService, 
ep.getObject().asResource());
+    static void accFusekiEndpoints(Set<Endpoint> endpoints, Graph 
configuration, Node fusekiService, DatasetDescriptionMap dsDescMap) {
+        List<Node> endpointsDesc = G.listSP(configuration, fusekiService, 
pEndpoint);
+        endpointsDesc.forEach(ep-> {
+            if ( ! isResource(ep) )
+                throw new FusekiConfigException("Literal for fuseki:endpoint: 
expected blank node or resource: "+displayStr(configuration, fusekiService));
+            Endpoint endpoint = buildEndpoint(configuration, fusekiService, 
ep);
             endpoints.add(endpoint);
         });
     }
@@ -505,51 +550,50 @@ public class FusekiConfig {
      *     ] ;
      * </pre>
      */
-    private static Endpoint buildEndpoint(Resource fusekiService, Resource 
endpoint) {
+    private static Endpoint buildEndpoint(Graph configuration, Node 
fusekiService, Node endpoint) {
         // Endpoints are often blank nodes so use fusekiService in error 
messages.
         // fuseki:operation
-        RDFNode opResource = getZeroOrOne(endpoint, pOperation);
+        Node opRef = BuildLib.getOne(configuration, endpoint, pOperation);
         Operation op = null;
-        if ( opResource != null ) {
-            if ( ! opResource.isResource() || opResource.isAnon() )
-                throw exception("Blank node endpoint operation in service %s", 
nodeLabel(fusekiService));
-            Node opRef = opResource.asNode();
+        if ( opRef != null ) {
+            if ( G.isBlank(opRef) )
+                throw exception("Blank node endpoint operation in service %s", 
displayStr(configuration, fusekiService));
             op = Operation.get(opRef);
         }
 
         // fuseki:implementation - checking only, not active.
         if ( op == null ) {
-            RDFNode rImpl = getZeroOrOne(endpoint, pImplementation);
+            Node rImpl = getZeroOrOne(configuration, endpoint, 
pImplementation);
             if ( rImpl == null )
-                throw exception("No implementation for fuseki:operation '%s' 
in service %s", nodeLabel(opResource), nodeLabel(fusekiService));
+                throw exception("No implementation for fuseki:operation '%s' 
in service %s", displayStr(configuration, opRef), displayStr(configuration, 
fusekiService));
             // Global registry. Replace existing registry.
-            Pair<Operation, ActionService> x = 
BuildLib.loadOperationActionService(rImpl);
+            Pair<Operation, ActionService> x = 
BuildLib.loadOperationActionService(configuration, rImpl);
             Operation op2 = x.getLeft();
             ActionService proc = x.getRight();
             if ( op2 == null )
-                throw exception("Failed to load implementation for 
fuseki:operation '%s' in service %s", nodeLabel(opResource), 
nodeLabel(fusekiService));
+                throw exception("Failed to load implementation for 
fuseki:operation '%s' in service %s", displayStr(configuration, opRef), 
displayStr(configuration, fusekiService));
             op = op2;
             // Using a blank node (!) for the operation means this is safe!
             // OperationRegistry.get().register(op2, proc);
         }
 
         // fuseki:allowedUsers
-        AuthPolicy authPolicy = FusekiConfig.allowedUsers(endpoint);
+        AuthPolicy authPolicy = FusekiConfig.allowedUsers(configuration, 
endpoint);
 
         // fuseki:name
-        RDFNode epNameR = getZeroOrOne(endpoint, pEndpointName);
-        String epName = null;
-        if ( epNameR == null ) {
+        Node epNameN = getZeroOrOne(configuration, endpoint, pEndpointName);
+        String epName;
+        if ( epNameN == null ) {
 //            // Make required to give "" for dataset, not default to dataset 
if missing.
 //            throw exception("No service name for endpoint", fusekiService, 
ep, pServiceName);
             epName = Endpoint.DatasetEP.string;
         } else {
-            if ( ! epNameR.isLiteral() )
+            if ( ! G.isString(epNameN) )
                 throw exception("Not a literal for service name for endpoint", 
fusekiService, endpoint, pEndpointName);
-            epName = epNameR.asLiteral().getLexicalForm();
+            epName = epNameN.getLiteralLexicalForm();
         }
 
-        Context cxt = parseContext(endpoint);
+        Context cxt = parseContext(configuration, endpoint);
 
         // Per-endpoint context.
         // Could add special names:
@@ -576,33 +620,34 @@ public class FusekiConfig {
     //    fuseki:serviceQuery "sparql";
     //or
     //    fuseki:serviceQuery [ fuseki:name "sparql" ; fuseki:allowedUsers 
(..) ];
-    private static void accEndpointOldStyle(Collection<Endpoint> endpoints, 
Operation operation, Resource svc, Property property) {
-        String p = "<"+property.getURI()+">";
-        ResultSet rs = BuildLib.query("SELECT * { ?svc " + p + " ?ep}", 
svc.getModel(), "svc", svc);
-        for (; rs.hasNext(); ) {
-            QuerySolution soln = rs.next();
-            // No policy yet - set below if one is found.
+    private static void accEndpointOldStyle(Collection<Endpoint> endpoints, 
Operation operation, Graph configuration, Node svc, Node endpointProperty) {
+
+        List<Node> endPts = G.listSP(configuration, svc, endpointProperty);
+        endPts.forEach(ep->{
             AuthPolicy authPolicy = null;
-            RDFNode ep = soln.get("ep");
             String endpointName = null;
             if ( ep.isLiteral() )
                 // fuseki:serviceQuery "sparql"
-                endpointName = soln.getLiteral("ep").getLexicalForm();
-            else if ( ep.isResource() ) {
-                Resource r = (Resource)ep;
+                endpointName = ep.getLiteralLexicalForm();
+            else if ( isResource(ep) ) {
                 try {
                     // [ fuseki:name ""; fuseki:allowedUsers ( "" "" ) ]
-                    Statement stmt = r.getProperty(FusekiVocab.pEndpointName);
-                    if ( stmt == null )
-                        throw new FusekiConfigException("Expected property 
<"+FusekiVocab.pEndpointName+"> with <"+property.getURI()+"> for <"+svc+">");
-                    endpointName = stmt.getString();
-                    List<RDFNode> x = GraphUtils.multiValue(r, 
FusekiVocab.pAllowedUsers);
+
+                    List<Node> named = G.listSP(configuration, ep, 
FusekiVocabG.pEndpointName);
+                    if ( named.isEmpty() )
+                        throw new FusekiConfigException("Expected property 
<"+FusekiVocabG.pEndpointName+"> with <"+endpointProperty.getURI()+"> for 
"+BuildLib.displayStr(configuration, svc));
+                    if ( named.size() > 1 )
+                        throw new FusekiConfigException("Multiple property 
values for <"+FusekiVocabG.pEndpointName+"> with 
<"+endpointProperty.getURI()+"> for "+BuildLib.displayStr(configuration, svc));
+                    endpointName = named.get(0).getLiteralLexicalForm();
+                    // XXX Necessary? check
+                    List<Node> x = G.listSP(configuration, ep, 
FusekiVocabG.pAllowedUsers);
                     if ( x.size() > 1 )
-                        throw new FusekiConfigException("Multiple 
fuseki:"+FusekiVocab.pAllowedUsers.getLocalName()+" for "+r);
+                        throw new FusekiConfigException("Multiple 
fuseki:"+FusekiVocabG.pAllowedUsers.getLocalName()+" for 
"+displayStr(configuration, ep));
+                    // Check
                     if ( ! x.isEmpty() )
-                        authPolicy = allowedUsers(r);
+                        authPolicy = allowedUsers(configuration, ep);
                 } catch(JenaException | ClassCastException ex) {
-                    throw new FusekiConfigException("Failed to parse endpoint: 
"+r);
+                    throw new FusekiConfigException("Failed to parse endpoint: 
"+displayStr(configuration, ep));
                 }
             } else {
                 throw new FusekiConfigException("Unrecognized: "+ep);
@@ -612,7 +657,7 @@ public class FusekiConfig {
                 endpointName = null;
             Endpoint endpoint = Endpoint.create(operation, endpointName, 
authPolicy);
             endpoints.add(endpoint);
-        }
+        });
     }
 
     private static void accEndpoint(Collection<Endpoint> endpoints, Operation 
operation) {
@@ -630,26 +675,37 @@ public class FusekiConfig {
         endpoints.add(endpoint);
     }
 
+    @Deprecated
     public static Dataset getDataset(Resource datasetDesc, 
DatasetDescriptionMap dsDescMap) {
+        DatasetGraph dsg = getDataset(datasetDesc.getModel().getGraph(), 
datasetDesc.asNode(), dsDescMap);
+        return DatasetFactory.wrap(dsg);
+    }
+
+    public static DatasetGraph getDataset(Graph configuration, Node 
datasetDesc, DatasetDescriptionMap dsDescMap) {
         // check if this one already built
         // This is absolute and does not require a NamedDatasetAssembler and 
to have a ja:name.
         // ja:name/NamedDatasetAssembler must be used if the service datasets 
need to
         // wire up sharing of a graph of datasets (not TDB).
 
-        Dataset ds = dsDescMap.get(datasetDesc);
-        if ( ds != null )
-            return ds;
+        DatasetGraph dsg = dsDescMap.get(datasetDesc);
+        if ( dsg != null )
+            return dsg;
 
         // Not seen before.
         // Check if the description is in the model.
-        if ( !datasetDesc.hasProperty(RDF.type) )
-            throw new FusekiConfigException("No rdf:type for dataset " + 
nodeLabel(datasetDesc));
+        if ( ! G.hasProperty(configuration, datasetDesc, RDF.Nodes.type) )
+            throw new FusekiConfigException("No rdf:type for dataset " + 
displayStr(configuration, datasetDesc));
 
         // Should have been done already. e.g. 
ActionDatasets.execPostContainer,
         // AssemblerUtils.readAssemblerFile < FusekiServer.parseConfigFile.
         //AssemblerUtils.addRegistered(datasetDesc.getModel());
-        ds = (Dataset)Assembler.general.open(datasetDesc);
-        dsDescMap.register(datasetDesc, ds);
-        return ds;
+
+        Resource r = resource(configuration, datasetDesc);
+        Dataset ds = (Dataset)Assembler.general.open(r);
+        if ( ds == null )
+            throw new FusekiConfigException("Bad description of a dataset: " + 
displayStr(configuration, datasetDesc));
+        dsg = ds.asDatasetGraph();
+        dsDescMap.register(datasetDesc, dsg);
+        return dsg;
     }
 }
diff --git 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/BuildLib.java
 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/model/BuildLibM.java
similarity index 94%
copy from 
jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/BuildLib.java
copy to 
jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/model/BuildLibM.java
index 302496b0b6..cc00bb01b8 100644
--- 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/BuildLib.java
+++ 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/model/BuildLibM.java
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-package org.apache.jena.fuseki.build;
+package org.apache.jena.fuseki.build.model;
 
 import static org.apache.jena.fuseki.build.FusekiPrefixes.PREFIXES;
 import static org.apache.jena.riot.out.NodeFmtLib.displayStr;
@@ -44,9 +44,9 @@ import org.apache.jena.vocabulary.RDFS;
 /**
  * Library code for operations related to building Fuseki servers and services.
  */
-/*package*/ class BuildLib {
+/*package*/ class BuildLibM {
 
-    private BuildLib() {}
+    private BuildLibM() {}
 
     // ---- Helper code
     /*package*/ static ResultSet query(String string, Model m) {
@@ -107,12 +107,12 @@ import org.apache.jena.vocabulary.RDFS;
     }
 
     /*package*/ static RDFNode getOne(Resource svc, Property property) {
-        ResultSet rs = BuildLib.query("SELECT * { ?svc <" + property.getURI() 
+ "> ?x}", svc.getModel(), "svc", svc);
+        ResultSet rs = BuildLibM.query("SELECT * { ?svc <" + property.getURI() 
+ "> ?x}", svc.getModel(), "svc", svc);
         if ( !rs.hasNext() )
-            throw new FusekiConfigException("No property '" + property + "' 
for service " + BuildLib.nodeLabel(svc));
+            throw new FusekiConfigException("No property '" + property + "' 
for service " + BuildLibM.nodeLabel(svc));
         RDFNode x = rs.next().get("x");
         if ( rs.hasNext() )
-            throw new FusekiConfigException("Multiple properties '" + property 
+ "' for service " + BuildLib.nodeLabel(svc));
+            throw new FusekiConfigException("Multiple properties '" + property 
+ "' for service " + BuildLibM.nodeLabel(svc));
         return x;
     }
 
@@ -122,7 +122,7 @@ import org.apache.jena.vocabulary.RDFS;
      * the difference between "not present" and an empty list value.
      */
     /*package*/ static Collection<RDFNode> getAll(Resource resource, String 
property) {
-        ResultSet rs = BuildLib.query("SELECT * { ?subject " + property + " 
?x}", resource.getModel(), "subject", resource);
+        ResultSet rs = BuildLibM.query("SELECT * { ?subject " + property + " 
?x}", resource.getModel(), "subject", resource);
         if ( ! rs.hasNext() )
             return null;
         List<RDFNode> results = new ArrayList<>();
diff --git 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/DatasetDescriptionMap.java
 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/model/DatasetDescriptionMapM.java
similarity index 93%
copy from 
jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/DatasetDescriptionMap.java
copy to 
jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/model/DatasetDescriptionMapM.java
index 647aa94959..6595ebe657 100644
--- 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/DatasetDescriptionMap.java
+++ 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/model/DatasetDescriptionMapM.java
@@ -16,7 +16,7 @@
  * limitations under the License.
  */
 
-package org.apache.jena.fuseki.build;
+package org.apache.jena.fuseki.build.model;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -33,11 +33,11 @@ import org.apache.jena.rdf.model.Resource;
  * corresponds to one dataset object when multiple services refer to the
  * same dataset.
  */
-public class DatasetDescriptionMap  {
+class DatasetDescriptionMapM  {
 
        private Map<Resource, Dataset> map = new HashMap<>();
 
-       public DatasetDescriptionMap() {}
+       /*package*/ DatasetDescriptionMapM() {}
 
     public void register(Resource node, Dataset ds) {
         Dataset dsCurrent = map.get(node);
diff --git 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/model/FusekiConfigM.java
similarity index 71%
copy from 
jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
copy to 
jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/model/FusekiConfigM.java
index cacbb712b0..7564e973cd 100644
--- 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
+++ 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/model/FusekiConfigM.java
@@ -16,45 +16,34 @@
  * limitations under the License.
  */
 
-package org.apache.jena.fuseki.build;
+package org.apache.jena.fuseki.build.model;
 
 import static java.lang.String.format;
-import static java.util.stream.Collectors.toList;
-import static org.apache.jena.fuseki.build.BuildLib.getZeroOrOne;
-import static org.apache.jena.fuseki.build.BuildLib.nodeLabel;
+import static org.apache.jena.fuseki.build.model.BuildLibM.getZeroOrOne;
+import static org.apache.jena.fuseki.build.model.BuildLibM.nodeLabel;
 import static org.apache.jena.fuseki.server.FusekiVocab.*;
-import static org.apache.jena.riot.RDFLanguages.filenameToLang;
-import static org.apache.jena.riot.RDFParserRegistry.isRegistered;
 
-import java.io.File;
-import java.io.IOException;
 import java.lang.reflect.Method;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
 import java.util.*;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.jena.assembler.Assembler;
-import org.apache.jena.assembler.JA;
-import org.apache.jena.atlas.lib.IRILib;
 import org.apache.jena.atlas.lib.Pair;
 import org.apache.jena.datatypes.xsd.XSDDatatype;
 import org.apache.jena.fuseki.Fuseki;
 import org.apache.jena.fuseki.FusekiConfigException;
 import org.apache.jena.fuseki.FusekiException;
-import org.apache.jena.fuseki.auth.Auth;
 import org.apache.jena.fuseki.auth.AuthPolicy;
 import org.apache.jena.fuseki.auth.AuthPolicyList;
+import org.apache.jena.fuseki.build.FusekiConfig;
 import org.apache.jena.fuseki.server.*;
 import org.apache.jena.fuseki.servlets.ActionService;
+import org.apache.jena.graph.Graph;
 import org.apache.jena.graph.Node;
 import org.apache.jena.query.Dataset;
 import org.apache.jena.query.QuerySolution;
 import org.apache.jena.query.ResultSet;
 import org.apache.jena.rdf.model.*;
-import org.apache.jena.rdf.model.impl.Util;
-import org.apache.jena.riot.Lang;
 import org.apache.jena.shared.JenaException;
 import org.apache.jena.sparql.core.DatasetGraph;
 import org.apache.jena.sparql.core.assembler.AssemblerUtils;
@@ -66,7 +55,8 @@ import org.apache.jena.vocabulary.RDF;
 import org.slf4j.Logger;
 
 /** Functions to setup and act on the configuration of a Fuseki server */
-public class FusekiConfig {
+//public
+class FusekiConfigM {
     private static Logger log = Fuseki.configLog;
 
     // The default setup of a DataService.
@@ -98,46 +88,51 @@ public class FusekiConfig {
 
     /** Convenience operation to populate a {@link DataService} with the 
conventional default services. */
     public static DataService.Builder populateStdServices(DataService.Builder 
dataServiceBuilder, boolean allowUpdate) {
-        Set<Endpoint> endpoints = new HashSet<>();
-        if ( allowUpdate ) {
-            stdWrite.forEach((name, op) -> accEndpoint(endpoints, op, name));
-            stdDatasetWrite.forEach(op -> accEndpoint(endpoints, op));
-        } else {
-            stdRead.forEach((name, op) -> accEndpoint(endpoints, op, name));
-            stdDatasetRead.forEach(op -> accEndpoint(endpoints, op));
-            if ( FusekiExt.extraOperationServicesRead != null )
-                FusekiExt.extraOperationServicesRead.forEach((name, op) -> 
accEndpoint(endpoints, op, name));
-        }
-        endpoints.forEach(dataServiceBuilder::addEndpoint);
-        return dataServiceBuilder;
-    }
-
-    public static void addDataService(DataAccessPointRegistry 
dataAccessPoints, String name, DataService dataService) {
-        name = DataAccessPoint.canonical(name);
-        if ( dataAccessPoints.isRegistered(name) )
-            throw new FusekiConfigException("Data service name already 
registered: "+name);
-        DataAccessPoint dap = new DataAccessPoint(name, dataService);
-        dataAccessPoints.register(dap);
+        return FusekiConfig.populateStdServices(dataServiceBuilder, 
allowUpdate);
+
+//        Set<Endpoint> endpoints = new HashSet<>();
+//        if ( allowUpdate ) {
+//            stdWrite.forEach((name, op) -> accEndpoint(endpoints, op, name));
+//            stdDatasetWrite.forEach(op -> accEndpoint(endpoints, op));
+//        } else {
+//            stdRead.forEach((name, op) -> accEndpoint(endpoints, op, name));
+//            stdDatasetRead.forEach(op -> accEndpoint(endpoints, op));
+//            if ( FusekiExt.extraOperationServicesRead != null )
+//                FusekiExt.extraOperationServicesRead.forEach((name, op) -> 
accEndpoint(endpoints, op, name));
+//        }
+//        endpoints.forEach(dataServiceBuilder::addEndpoint);
+//        return dataServiceBuilder;
     }
 
-    public static void addDataset(DataAccessPointRegistry dataAccessPoints, 
String name, DatasetGraph dsg, boolean withUpdate) {
-        name = DataAccessPoint.canonical(name);
-        if ( dataAccessPoints.isRegistered(name) )
-            throw new FusekiConfigException("Data service name already 
registered: "+name);
-        DataService dataService = buildDataServiceStd(dsg, withUpdate);
-        DataAccessPoint dap = new DataAccessPoint(name, dataService);
-        dataAccessPoints.register(dap);
-    }
+//    private static void addDataService(DataAccessPointRegistry 
dataAccessPoints, String name, DataService dataService) {
+//
+//        name = DataAccessPoint.canonical(name);
+//        if ( dataAccessPoints.isRegistered(name) )
+//            throw new FusekiConfigException("Data service name already 
registered: "+name);
+//        DataAccessPoint dap = new DataAccessPoint(name, dataService);
+//        dataAccessPoints.register(dap);
+//    }
+//
+//    public static void addDataset(DataAccessPointRegistry dataAccessPoints, 
String name, DatasetGraph dsg, boolean withUpdate) {
+//        name = DataAccessPoint.canonical(name);
+//        if ( dataAccessPoints.isRegistered(name) )
+//            throw new FusekiConfigException("Data service name already 
registered: "+name);
+//        DataService dataService = buildDataServiceStd(dsg, withUpdate);
+//        DataAccessPoint dap = new DataAccessPoint(name, dataService);
+//        dataAccessPoints.register(dap);
+//    }
 
     public static DataService buildDataServiceStd(DatasetGraph dsg, boolean 
withUpdate) {
-        return DataService.newBuilder(dsg)
-                .withStdServices(withUpdate)
-                .build();
+        return FusekiConfig.buildDataServiceStd(dsg, withUpdate);
+//        return DataService.newBuilder(dsg)
+//                .withStdServices(withUpdate)
+//                .build();
     }
 
     public static void removeDataset(DataAccessPointRegistry dataAccessPoints, 
String name) {
-        name = DataAccessPoint.canonical(name);
-        dataAccessPoints.remove(name);
+        FusekiConfig.removeDataset(dataAccessPoints, name);
+//        name = DataAccessPoint.canonical(name);
+//        dataAccessPoints.remove(name);
     }
 
     /** Get the allowed users on a resource.
@@ -146,28 +141,29 @@ public class FusekiConfig {
      * @return RequestAuthorization
      */
     public static AuthPolicy allowedUsers(Resource resource) {
-        if ( resource == null )
-            return null;
-        Collection<RDFNode> allowedUsers = BuildLib.getAll(resource, 
"fu:"+pAllowedUsers.getLocalName());
-        if ( allowedUsers == null )
-            // Indicate no settings.
-            return null;
-        // Check all values are simple strings
-        List<String> bad = allowedUsers.stream()
-            .map(RDFNode::asNode)
-            .filter(rn -> ! Util.isSimpleString(rn))
-            .map(rn->rn.toString())
-            .collect(toList());
-        if ( ! bad.isEmpty() ) {
-            //Fuseki.configLog.error(format("User names must be a simple 
string: bad = %s", bad));
-            throw new FusekiConfigException(format("User names should be a 
simple string: bad = %s", bad));
-        }
-        // RDFNodes/literals to strings.
-        Collection<String> userNames = allowedUsers.stream()
-            .map(RDFNode::asNode)
-            .map(Node::getLiteralLexicalForm)
-            .collect(toList());
-        return Auth.policyAllowSpecific(userNames);
+        return FusekiConfig.allowedUsers(resource.getModel().getGraph(), 
resource.asNode());
+//        if ( resource == null )
+//            return null;
+//        Collection<RDFNode> allowedUsers = BuildLib.getAll(resource, 
"fu:"+pAllowedUsers.getLocalName());
+//        if ( allowedUsers == null )
+//            // Indicate no settings.
+//            return null;
+//        // Check all values are simple strings
+//        List<String> bad = allowedUsers.stream()
+//            .map(RDFNode::asNode)
+//            .filter(rn -> ! Util.isSimpleString(rn))
+//            .map(rn->rn.toString())
+//            .collect(toList());
+//        if ( ! bad.isEmpty() ) {
+//            //Fuseki.configLog.error(format("User names must be a simple 
string: bad = %s", bad));
+//            throw new FusekiConfigException(format("User names should be a 
simple string: bad = %s", bad));
+//        }
+//        // RDFNodes/literals to strings.
+//        Collection<String> userNames = allowedUsers.stream()
+//            .map(RDFNode::asNode)
+//            .map(Node::getLiteralLexicalForm)
+//            .collect(toList());
+//        return Auth.policyAllowSpecific(userNames);
     }
 
     /**
@@ -183,13 +179,14 @@ public class FusekiConfig {
      * </ul>
      */
     public static List<DataAccessPoint> processServerConfiguration(Model 
configuration, Context context) {
-        Resource server = findServer(configuration);
-        if ( server != null ) {
-            mergeContext(server, context);
-            processLoadClass(server);
-        }
-        // Process services, whether via server ja:services or, if absent, by 
finding by type.
-        return servicesAndDatasets$(server, configuration);
+        return 
FusekiConfig.processServerConfiguration(configuration.getGraph(), context);
+//        Resource server = findServer(configuration);
+//        if ( server != null ) {
+//            mergeContext(server, context);
+//            processLoadClass(server);
+//        }
+//        // Process services, whether via server ja:services or, if absent, 
by finding by type.
+//        return servicesAndDatasets$(server, configuration);
     }
 
     /* Find the server resource in a configuration file.
@@ -197,16 +194,29 @@ public class FusekiConfig {
      * Raises {@link FusekiConfigException} is there are more than one.
      */
     public static Resource findServer(Model model) {
-        List<Resource> servers = GraphUtils.listResourcesByType(model, 
FusekiVocab.tServer);
-        if ( servers.size() == 0 )
-            // "No server" is fine.
+        Node n = FusekiConfig.findServer(model.getGraph());
+        if ( n == null )
             return null;
-        if ( servers.size() > 1 )
-            throw new FusekiConfigException(servers.size()
-                                            + " servers found (must be exactly 
one in a configuration file)");
-        // ---- Server
-        Resource server = servers.get(0);
-        return server;
+        return resourceAdapter(model.getGraph(), n);
+
+//        List<Resource> servers = GraphUtils.listResourcesByType(model, 
FusekiVocab.tServer);
+//        if ( servers.size() == 0 )
+//            // "No server" is fine.
+//            return null;
+//        if ( servers.size() > 1 )
+//            throw new FusekiConfigException(servers.size()
+//                                            + " servers found (must be 
exactly one in a configuration file)");
+//        // ---- Server
+//        Resource server = servers.get(0);
+//        return server;
+    }
+
+    private static Resource resourceAdapter(Graph graph, Node node) {
+        Model m = ModelFactory.createModelForGraph(graph);
+        RDFNode rNode = m.asRDFNode(node);
+        if ( ! rNode.isResource() )
+            throw new FusekiConfigException("Not a resource: "+node);
+        return rNode.asResource();
     }
 
     /**
@@ -233,30 +243,31 @@ public class FusekiConfig {
      * Process any {@code ja:loadClass}
      */
     public static void processLoadClass(Resource server) {
-        if ( server == null )
-            return;
-        StmtIterator sIter = server.listProperties(JA.loadClass);
-        for (; sIter.hasNext(); ) {
-            Statement s = sIter.nextStatement();
-            RDFNode rn = s.getObject();
-            String className = null;
-            if ( rn instanceof Resource res ) {
-                String uri = res.getURI();
-                if ( uri == null ) {
-                    log.warn("Blank node for class to load");
-                    continue;
-                }
-                String javaScheme = "java:";
-                if ( !uri.startsWith(javaScheme) ) {
-                    log.warn("Class to load is not 'java:': " + uri);
-                    continue;
-                }
-                className = uri.substring(javaScheme.length());
-            }
-            if ( rn instanceof Literal lit)
-                className = lit.getLexicalForm();
-            loadAndInit(className);
-        }
+        FusekiConfig.processLoadClass(server.getModel().getGraph(), 
server.asNode());
+//        if ( server == null )
+//            return;
+//        StmtIterator sIter = server.listProperties(JA.loadClass);
+//        for (; sIter.hasNext(); ) {
+//            Statement s = sIter.nextStatement();
+//            RDFNode rn = s.getObject();
+//            String className = null;
+//            if ( rn instanceof Resource res ) {
+//                String uri = res.getURI();
+//                if ( uri == null ) {
+//                    log.warn("Blank node for class to load");
+//                    continue;
+//                }
+//                String javaScheme = "java:";
+//                if ( !uri.startsWith(javaScheme) ) {
+//                    log.warn("Class to load is not 'java:': " + uri);
+//                    continue;
+//                }
+//                className = uri.substring(javaScheme.length());
+//            }
+//            if ( rn instanceof Literal lit)
+//                className = lit.getLexicalForm();
+//            loadAndInit(className);
+//        }
     }
 
     /** Find and process datasets and services in a configuration file.
@@ -269,29 +280,19 @@ public class FusekiConfig {
         return servicesAndDatasets$(server, model);
     }
 
-    /** Find and process datasets and services in a configuration file
-     * starting from {@code server} which can have a {@code fuseki:services ( 
.... )}
-     * but, if not found, all {@code rdf:type fuseki:services} are processed.
-     */
-    private
-    /*public*/ static List<DataAccessPoint> 
servicesAndDatasets_notUsed(Resource server) {
-        Objects.requireNonNull(server);
-        return servicesAndDatasets$(server, server.getModel());
-    }
-
     private static List<DataAccessPoint> servicesAndDatasets$(Resource server, 
Model model) {
-        DatasetDescriptionMap dsDescMap = new DatasetDescriptionMap();
+        DatasetDescriptionMapM dsDescMap = new DatasetDescriptionMapM();
         NamedDatasetAssembler.sharedDatasetPool.clear();
         // ---- Services
         // Server to services.
-        ResultSet rs = BuildLib.query("SELECT * { ?s fu:services [ list:member 
?service ] }", model, "s", server);
+        ResultSet rs = BuildLibM.query("SELECT * { ?s fu:services [ 
list:member ?service ] }", model, "s", server);
         List<DataAccessPoint> accessPoints = new ArrayList<>();
 
         // If none, look for services by type.
         if ( ! rs.hasNext() )
             // No "fu:services ( .... )" so try looking for services directly.
             // This means Fuseki2, service configuration files (no server 
section) work for --conf.
-            rs = BuildLib.query("SELECT ?service { ?service a fu:Service }", 
model);
+            rs = BuildLibM.query("SELECT ?service { ?service a fu:Service }", 
model);
 
         // rs is a result set of services to process.
         for (; rs.hasNext(); ) {
@@ -327,43 +328,44 @@ public class FusekiConfig {
 
     /** Read service descriptions in the given directory */
     public static List<DataAccessPoint> readConfigurationDirectory(String dir) 
{
-        Path pDir = Path.of(dir).normalize();
-        File dirFile = pDir.toFile();
-        if ( ! dirFile.exists() ) {
-            log.warn("Not found: directory for assembler files for services: 
'"+dir+"'");
-            return Collections.emptyList();
-        }
-        if ( ! dirFile.isDirectory() ) {
-            log.warn("Not a directory: '"+dir+"'");
-            return Collections.emptyList();
-        }
-        // Files that are not hidden.
-        DirectoryStream.Filter<Path> filter = (entry)-> {
-            File f = entry.toFile();
-            final Lang lang = filenameToLang(f.getName());
-            return ! f.isHidden() && f.isFile() && lang != null && 
isRegistered(lang);
-        };
-
-        List<DataAccessPoint> dataServiceRef = new ArrayList<>();
-        try (DirectoryStream<Path> stream = Files.newDirectoryStream(pDir, 
filter)) {
-            for ( Path p : stream ) {
-                DatasetDescriptionMap dsDescMap = new DatasetDescriptionMap();
-                String fn = IRILib.filenameToIRI(p.toString());
-                log.info("Load configuration: "+fn);
-                Model m = readAssemblerFile(fn);
-                readConfiguration(m, dsDescMap, dataServiceRef);
-            }
-        } catch (IOException ex) {
-            log.warn("IOException:"+ex.getMessage(), ex);
-        }
-        return dataServiceRef;
+        return FusekiConfig.readConfigurationDirectory(dir);
+//        Path pDir = Path.of(dir).normalize();
+//        File dirFile = pDir.toFile();
+//        if ( ! dirFile.exists() ) {
+//            log.warn("Not found: directory for assembler files for services: 
'"+dir+"'");
+//            return Collections.emptyList();
+//        }
+//        if ( ! dirFile.isDirectory() ) {
+//            log.warn("Not a directory: '"+dir+"'");
+//            return Collections.emptyList();
+//        }
+//        // Files that are not hidden.
+//        DirectoryStream.Filter<Path> filter = (entry)-> {
+//            File f = entry.toFile();
+//            final Lang lang = filenameToLang(f.getName());
+//            return ! f.isHidden() && f.isFile() && lang != null && 
isRegistered(lang);
+//        };
+//
+//        List<DataAccessPoint> dataServiceRef = new ArrayList<>();
+//        try (DirectoryStream<Path> stream = Files.newDirectoryStream(pDir, 
filter)) {
+//            for ( Path p : stream ) {
+//                DatasetDescriptionMap dsDescMap = new 
DatasetDescriptionMap();
+//                String fn = IRILib.filenameToIRI(p.toString());
+//                log.info("Load configuration: "+fn);
+//                Model m = readAssemblerFile(fn);
+//                readConfiguration(m, dsDescMap, dataServiceRef);
+//            }
+//        } catch (IOException ex) {
+//            log.warn("IOException:"+ex.getMessage(), ex);
+//        }
+//        return dataServiceRef;
     }
 
     /** Read a configuration in a model.
      * Allow dataset descriptions to be carried over from another place.
      * Add to a list.
      */
-    private static void readConfiguration(Model m, DatasetDescriptionMap 
dsDescMap, List<DataAccessPoint> dataServiceRef) {
+    private static void readConfiguration(Model m, DatasetDescriptionMapM 
dsDescMap, List<DataAccessPoint> dataServiceRef) {
         List<Resource> services = GraphUtils.listResourcesByType(m, 
FusekiVocab.fusekiService);
 
         if ( services.size() == 0 ) {
@@ -379,8 +381,8 @@ public class FusekiConfig {
     }
 
     /** Build a DataAccessPoint, including DataService, from the description 
at Resource svc */
-    public static DataAccessPoint buildDataAccessPoint(Resource svc, 
DatasetDescriptionMap dsDescMap) {
-        RDFNode n = BuildLib.getOne(svc, FusekiVocab.pServiceName);
+    public static DataAccessPoint buildDataAccessPoint(Resource svc, 
DatasetDescriptionMapM dsDescMap) {
+        RDFNode n = BuildLibM.getOne(svc, FusekiVocab.pServiceName);
         try {
             if ( ! n.isLiteral() )
                 throw new FusekiConfigException("Not a literal for access 
point name: "+FmtUtils.stringForRDFNode(n));
@@ -402,8 +404,8 @@ public class FusekiConfig {
         }
     }
 
-    private static DataService.Builder buildDataService(Resource 
fusekiService, DatasetDescriptionMap dsDescMap) {
-        Resource datasetDesc = (Resource)BuildLib.getOne(fusekiService, 
FusekiVocab.pDataset);
+    private static DataService.Builder buildDataService(Resource 
fusekiService, DatasetDescriptionMapM dsDescMap) {
+        Resource datasetDesc = (Resource)BuildLibM.getOne(fusekiService, 
FusekiVocab.pDataset);
         Dataset ds = getDataset(datasetDesc, dsDescMap);
         DataService.Builder dataService = 
DataService.newBuilder(ds.asDatasetGraph());
         Set<Endpoint> endpoints1 = new HashSet<>();
@@ -477,7 +479,7 @@ public class FusekiConfig {
 
     /** Find and parse {@code fuseki:endpoint} descriptions. */
     private
-    static void accFusekiEndpoints(Set<Endpoint> endpoints, Resource 
fusekiService, DatasetDescriptionMap dsDescMap) {
+    static void accFusekiEndpoints(Set<Endpoint> endpoints, Resource 
fusekiService, DatasetDescriptionMapM dsDescMap) {
         StmtIterator endpointsDesc = fusekiService.listProperties(pEndpoint);
         endpointsDesc.forEachRemaining(ep-> {
             if ( ! ep.getObject().isResource() )
@@ -523,7 +525,7 @@ public class FusekiConfig {
             if ( rImpl == null )
                 throw exception("No implementation for fuseki:operation '%s' 
in service %s", nodeLabel(opResource), nodeLabel(fusekiService));
             // Global registry. Replace existing registry.
-            Pair<Operation, ActionService> x = 
BuildLib.loadOperationActionService(rImpl);
+            Pair<Operation, ActionService> x = 
BuildLibM.loadOperationActionService(rImpl);
             Operation op2 = x.getLeft();
             ActionService proc = x.getRight();
             if ( op2 == null )
@@ -534,7 +536,7 @@ public class FusekiConfig {
         }
 
         // fuseki:allowedUsers
-        AuthPolicy authPolicy = FusekiConfig.allowedUsers(endpoint);
+        AuthPolicy authPolicy = allowedUsers(endpoint);
 
         // fuseki:name
         RDFNode epNameR = getZeroOrOne(endpoint, pEndpointName);
@@ -578,7 +580,7 @@ public class FusekiConfig {
     //    fuseki:serviceQuery [ fuseki:name "sparql" ; fuseki:allowedUsers 
(..) ];
     private static void accEndpointOldStyle(Collection<Endpoint> endpoints, 
Operation operation, Resource svc, Property property) {
         String p = "<"+property.getURI()+">";
-        ResultSet rs = BuildLib.query("SELECT * { ?svc " + p + " ?ep}", 
svc.getModel(), "svc", svc);
+        ResultSet rs = BuildLibM.query("SELECT * { ?svc " + p + " ?ep}", 
svc.getModel(), "svc", svc);
         for (; rs.hasNext(); ) {
             QuerySolution soln = rs.next();
             // No policy yet - set below if one is found.
@@ -630,7 +632,7 @@ public class FusekiConfig {
         endpoints.add(endpoint);
     }
 
-    public static Dataset getDataset(Resource datasetDesc, 
DatasetDescriptionMap dsDescMap) {
+    public static Dataset getDataset(Resource datasetDesc, 
DatasetDescriptionMapM dsDescMap) {
         // check if this one already built
         // This is absolute and does not require a NamedDatasetAssembler and 
to have a ja:name.
         // ja:name/NamedDatasetAssembler must be used if the service datasets 
need to
diff --git 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java
 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java
index 47974435d9..6d479743fc 100755
--- 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java
+++ 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocab.java
@@ -27,7 +27,8 @@ import org.apache.jena.rdf.model.ResourceFactory;
 
 public class FusekiVocab
 {
-    public static String NS = "http://jena.apache.org/fuseki#";;
+    // Keep in-step with FusekiVocabG (same constants, but as nodes).
+    public static final String NS = "http://jena.apache.org/fuseki#";;
 
     public static final Resource tServer            = resource("Server");
 
diff --git 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocabG.java
 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocabG.java
new file mode 100644
index 0000000000..44d07aa118
--- /dev/null
+++ 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/FusekiVocabG.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.server;
+
+import org.apache.jena.fuseki.FusekiException;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.irix.IRIException;
+import org.apache.jena.irix.IRIx;
+
+/**
+ * Fuseki Vocabulary - using {@link Node Nodes}.
+ */
+public class FusekiVocabG
+{
+    // Keep in-step with FusekiVocab (same constants, but as model resources 
and properties).
+    private static final String NS = FusekiVocab.NS;
+    public static String getURI() { return NS; }
+
+    public static final Node tServer            = resource("Server");
+
+    public static final Node fusekiService      = resource("Service");
+
+    public static final Node pServices          = property("services");
+
+    // Server endpoints.
+    public static final Node pServerPing        = property("pingEP");
+    public static final Node pServerStats       = property("statsEP");
+    public static final Node pServerMetrics     = property("metricsEP");
+    public static final Node pServerCompact     = property("compactEP");
+
+    // Server features
+    // Fuseki main - servlet context.
+    public static final Node pServerContextPath = property("contextPath");
+
+    // Endpoint description.
+    public static final Node pServiceName               = property("name");
+    public static final Node pEndpointName              = property("name");
+    public static final Node pPasswordFile              = property("passwd");
+    public static final Node pRealm                     = property("realm");
+    public static final Node pAuth                      = property("auth");
+    public static final Node pEndpoint                  = property("endpoint");
+    public static final Node pOperation                 = 
property("operation");
+    public static final Node pAllowedUsers              = 
property("allowedUsers");
+    public static final Node pTimeout                   = property("timeout");
+    public static final Node pImplementation            = 
property("implementation");
+    public static final Node pQueryLimit                = 
property("queryLimit");
+    public static final Node pUnionDefaultGraph         = 
property("unionDefaultGraph");
+    public static final Node pAllowTimeoutOverride      = 
property("allowTimeoutOverride");
+    public static final Node pMaximumTimeoutOverride    = 
property("maximumTimeoutOverride");
+    public static final Node pDataset                   = property("dataset");
+
+    // Endpoint description - old style.
+    public static final Node pServiceQueryEP                = 
property("serviceQuery");
+    public static final Node pServiceUpdateEP               = 
property("serviceUpdate");
+    public static final Node pServiceUploadEP               = 
property("serviceUpload");
+    public static final Node pServiceShaclEP                = 
property("serviceShacl");
+    public static final Node pServiceReadWriteGraphStoreEP  = 
property("serviceReadWriteGraphStore");
+    public static final Node pServiceReadGraphStoreEP       = 
property("serviceReadGraphStore");
+    // No longer used.
+//    public static final Node pServiceReadWriteQuadsEP       = 
property("serviceReadWriteQuads");
+//    public static final Node pServiceReadQuadsEP            = 
property("serviceReadQuads");
+
+    // Operation names : the standard operations.
+    // "alt" names are the same but using "_" not "-".
+    public static final Node opQuery       = resource("query");
+    public static final Node opUpdate      = resource("update");
+    public static final Node opUpload      = resource("upload");
+    public static final Node opGSP_r       = resource("gsp-r");
+    public static final Node opGSP_r_alt   = resource("gsp_r");
+    public static final Node opGSP_rw      = resource("gsp-rw");
+    public static final Node opGSP_rw_alt  = resource("gsp_rw");
+    public static final Node opNoOp        = resource("no-op");
+    public static final Node opNoOp_alt    = resource("no_op");
+    public static final Node opShacl       = resource("shacl");
+    public static final Node opPatch       = resource("patch");
+
+    public static final Node opPREFIXES_R       = resource("prefixes-r");
+    public static final Node opPREFIXES_RW      = resource("prefixes-rw");
+
+    private static Node resource(String localname) { return 
NodeFactory.createURI(iri(localname)); }
+    private static Node property(String localname) { return 
NodeFactory.createURI(iri(localname)); }
+
+    private static String iri(String localname) {
+        String uri = NS + localname;
+        try {
+            IRIx iri = IRIx.create(uri);
+            if ( ! iri.isReference() )
+                throw new FusekiException("Bad IRI (relative): "+uri);
+            return uri;
+        } catch (IRIException ex) {
+            throw new FusekiException("Bad IRI: "+uri);
+        }
+    }
+}
diff --git 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Operation.java
 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Operation.java
index 6c833c113f..d066b7a123 100644
--- 
a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Operation.java
+++ 
b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/server/Operation.java
@@ -29,7 +29,6 @@ import org.apache.jena.graph.Node;
 import org.apache.jena.graph.NodeFactory;
 import org.apache.jena.irix.IRIException;
 import org.apache.jena.irix.IRIx;
-import org.apache.jena.rdf.model.Resource;
 
 /**
  * Operations are symbol to look up in the {@link 
OperationRegistry#operationToHandler} map. The name
@@ -38,8 +37,6 @@ import org.apache.jena.rdf.model.Resource;
  */
 public class Operation {
 
-    private static String NS = FusekiVocab.NS;
-
     /** Create/intern. Maps short name to operation. */
     static private Map<Node, Operation> mgr = new HashMap<>();
 
@@ -77,26 +74,26 @@ public class Operation {
         return new Operation(id, shortName, lowercase(shortName), description);
     }
 
-    public static final Operation Query    = 
alloc(FusekiVocab.opQuery.asNode(),   "query",   "SPARQL Query");
-    public static final Operation Update   = 
alloc(FusekiVocab.opUpdate.asNode(),  "update",  "SPARQL Update");
-    public static final Operation GSP_R    = 
alloc(FusekiVocab.opGSP_r.asNode(),   "gsp-r",   "Graph Store Protocol (Read)");
-    public static final Operation GSP_RW   = 
alloc(FusekiVocab.opGSP_rw.asNode(),  "gsp-rw",  "Graph Store Protocol");
+    public static final Operation Query    = alloc(FusekiVocabG.opQuery,   
"query",   "SPARQL Query");
+    public static final Operation Update   = alloc(FusekiVocabG.opUpdate,  
"update",  "SPARQL Update");
+    public static final Operation GSP_R    = alloc(FusekiVocabG.opGSP_r,   
"gsp-r",   "Graph Store Protocol (Read)");
+    public static final Operation GSP_RW   = alloc(FusekiVocabG.opGSP_rw,  
"gsp-rw",  "Graph Store Protocol");
 
-    public static final Operation Shacl    = 
alloc(FusekiVocab.opShacl.asNode(),   "SHACL",   "SHACL Validation");
-    public static final Operation Upload   = 
alloc(FusekiVocab.opUpload.asNode(),  "upload",  "File Upload");
-    public static final Operation Patch    = 
alloc(FusekiVocab.opPatch.asNode(),   "patch",   "RDF Patch");
+    public static final Operation Shacl    = alloc(FusekiVocabG.opShacl,   
"SHACL",   "SHACL Validation");
+    public static final Operation Upload   = alloc(FusekiVocabG.opUpload,  
"upload",  "File Upload");
+    public static final Operation Patch    = alloc(FusekiVocabG.opPatch,   
"patch",   "RDF Patch");
 
-    public static final Operation NoOp     = 
alloc(FusekiVocab.opNoOp.asNode(),    "no-op",   "No Op");
+    public static final Operation NoOp     = alloc(FusekiVocabG.opNoOp,    
"no-op",   "No Op");
 
-    public static final Operation PREFIXES_R   = 
alloc(FusekiVocab.opPREFIXES_R.asNode(),   "prefixes-r",   "Read prefixes");
-    public static final Operation PREFIXES_RW  = 
alloc(FusekiVocab.opPREFIXES_RW.asNode(),  "prefixes-rw",  "Read-write 
prefixes");
+    public static final Operation PREFIXES_R   = 
alloc(FusekiVocabG.opPREFIXES_R,   "prefixes-r",   "Read prefixes");
+    public static final Operation PREFIXES_RW  = 
alloc(FusekiVocabG.opPREFIXES_RW,  "prefixes-rw",  "Read-write prefixes");
 
 
     static {
         // Not everyone will remember "_" vs "-" so ...
-        altName(FusekiVocab.opNoOp_alt,   FusekiVocab.opNoOp);
-        altName(FusekiVocab.opGSP_r_alt,  FusekiVocab.opGSP_r);
-        altName(FusekiVocab.opGSP_rw_alt, FusekiVocab.opGSP_rw);
+        altName(FusekiVocabG.opNoOp_alt,   FusekiVocabG.opNoOp);
+        altName(FusekiVocabG.opGSP_r_alt,  FusekiVocabG.opGSP_r);
+        altName(FusekiVocabG.opGSP_rw_alt, FusekiVocabG.opGSP_rw);
     }
 
     // -- Object
@@ -162,10 +159,6 @@ public class Operation {
         return name;
     }
 
-    private static void altName(Resource altName, Resource properName) {
-        altName(altName.asNode(), properName.asNode());
-    }
-
     private static void altName(Node altName, Node properName) {
         Operation op = mgr.get(properName);
         mgr.put(altName, op);
diff --git 
a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
 
b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
index a63361f5f4..3e00e103d5 100644
--- 
a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
+++ 
b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/FusekiServer.java
@@ -28,6 +28,7 @@ import java.util.*;
 import java.util.function.Function;
 import java.util.function.Predicate;
 
+
 import jakarta.servlet.Filter;
 import jakarta.servlet.ServletContext;
 import jakarta.servlet.http.HttpServlet;
@@ -57,14 +58,12 @@ import org.apache.jena.graph.Graph;
 import org.apache.jena.graph.Node;
 import org.apache.jena.query.Dataset;
 import org.apache.jena.rdf.model.*;
-import org.apache.jena.shared.JenaException;
 import org.apache.jena.sparql.core.DatasetGraph;
 import org.apache.jena.sparql.core.assembler.AssemblerUtils;
 import org.apache.jena.sparql.util.Context;
-import org.apache.jena.sparql.util.NotUniqueException;
-import org.apache.jena.sparql.util.graph.GraphUtils;
 import org.apache.jena.sys.JenaSystem;
 import org.apache.jena.system.G;
+import org.apache.jena.system.RDFDataException;
 import org.apache.jena.web.HttpSC;
 import org.eclipse.jetty.ee10.servlet.DefaultServlet;
 import org.eclipse.jetty.ee10.servlet.FilterHolder;
@@ -796,19 +795,7 @@ public class FusekiServer {
          */
         public Builder parseConfig(Model model) {
             requireNonNull(model, "model");
-            Resource server = FusekiConfig.findServer(model);
-            processConfigServerLevel(server);
-
-            // Process server and services, whether via server ja:services or, 
if absent, by finding by type.
-
-            // Context is only set, not deleted, in a configuration file.
-            Context settings = new Context();
-            List<DataAccessPoint> x = 
FusekiConfig.processServerConfiguration(model, settings);
-
-            // Side effect - sets global context.
-            Fuseki.getContext().putAll(settings);
-            // Can further modify the services in the configuration file.
-            x.forEach(dap->addDataAccessPoint(dap));
+            parseConfiguration(model.getGraph());
             configModel = model;
             return this;
         }
@@ -821,9 +808,31 @@ public class FusekiServer {
          * a text index.
          */
         public Builder parseConfig(Graph graph) {
-            return parseConfig(ModelFactory.createModelForGraph(graph));
+            requireNonNull(graph, "graph");
+            parseConfiguration(graph);
+            configModel = ModelFactory.createModelForGraph(graph);
+            return this;
         }
 
+        public void parseConfiguration(Graph graph) {
+            requireNonNull(graph, "graph");
+
+            Node server = FusekiConfig.findServer(graph);
+            processConfigServerLevel(graph, server);
+
+            // Process server and services, whether via server ja:services or, 
if absent, by finding by type.
+
+            // Context is only set, not deleted, in a configuration file.
+            Context settings = new Context();
+            List<DataAccessPoint> x = 
FusekiConfig.processServerConfiguration(graph, settings);
+
+            // Side effect - sets global context.
+            Fuseki.getContext().putAll(settings);
+            // Can further modify the services in the configuration file.
+            x.forEach(dap->addDataAccessPoint(dap));
+        }
+
+
         /** Add a {@link DataAccessPoint} as a builder. */
         private Builder addDataAccessPoint(DataAccessPoint dap) {
             if ( isRegistered(dap.getName()) )
@@ -852,29 +861,37 @@ public class FusekiServer {
         private void processConfigServerLevel(Resource server) {
             if ( server == null )
                 return;
+            processConfigServerLevel(server.getModel().getGraph(), 
server.asNode());
+        }
 
-            if ( server.hasProperty(FusekiVocab.pServerContextPath) )
-                contextPath(argString(server, FusekiVocab.pServerContextPath, 
"/"));
-            enablePing(argBoolean(server, FusekiVocab.pServerPing,  false));
-            enableStats(argBoolean(server, FusekiVocab.pServerStats, false));
-            enableMetrics(argBoolean(server, FusekiVocab.pServerMetrics, 
false));
-            enableCompact(argBoolean(server, FusekiVocab.pServerCompact, 
false));
-
-            processConfAuthentication(server);
+        private void processConfigServerLevel(Graph config, Node server) {
+            if ( server == null )
+                return;
 
-            serverAuth = FusekiConfig.allowedUsers(server);
+            if ( G.hasProperty(config, server, 
FusekiVocabG.pServerContextPath) )
+                contextPath(argString(config, server, 
FusekiVocabG.pServerContextPath, "/"));
+            enablePing(argBoolean(config, server, FusekiVocabG.pServerPing,  
false));
+            enableStats(argBoolean(config, server, FusekiVocabG.pServerStats, 
false));
+            enableMetrics(argBoolean(config, server, 
FusekiVocabG.pServerMetrics, false));
+            enableCompact(argBoolean(config, server, 
FusekiVocabG.pServerCompact, false));
+            processConfAuthentication(config, server);
+            serverAuth = FusekiConfig.allowedUsers(config, server);
         }
 
         /** Process password file, auth and realm settings on the server 
description. **/
         private void processConfAuthentication(Resource server) {
-            String passwdFile = GraphUtils.getAsStringValue(server, 
FusekiVocab.pPasswordFile);
+
+        }
+
+        private void processConfAuthentication(Graph config, Node server) {
+            String passwdFile = getAsString(config, server, 
FusekiVocabG.pPasswordFile);
             if ( passwdFile != null )
                 passwordFile(passwdFile);
-            String realmStr = GraphUtils.getAsStringValue(server, 
FusekiVocab.pRealm);
+            String realmStr = getAsString(config, server, FusekiVocabG.pRealm);
             if ( realmStr != null )
                 realm(realmStr);
 
-            String authStr = GraphUtils.getAsStringValue(server, 
FusekiVocab.pAuth);
+            String authStr = getAsString(config, server, FusekiVocabG.pAuth);
             if ( authStr != null ) {
                 AuthScheme authScheme = AuthScheme.scheme(authStr);
                 switch (authScheme) {
@@ -889,39 +906,49 @@ public class FusekiServer {
             }
         }
 
-        private static boolean argBoolean(Resource r, Property p, boolean 
dftValue) {
-            try { GraphUtils.atmostOneProperty(r, p); }
-            catch (NotUniqueException ex) {
-                throw new FusekiConfigException(ex.getMessage());
-            }
-            Statement stmt = r.getProperty(p);
-            if ( stmt == null )
-                return dftValue;
+        private static boolean argBoolean(Graph graph, Node r, Node p, boolean 
dftValue) {
             try {
-                return stmt.getBoolean();
-            } catch (JenaException ex) {
-                throw new FusekiConfigException("Not a boolean for '"+p+"' : 
"+stmt.getObject());
+                Boolean bool = getAsBoolean(graph, r, p);
+                if ( bool == null )
+                    return dftValue;
+                return bool;
+            } catch (RDFDataException ex) {
+                throw new FusekiConfigException("Boolean argument "+r+" "+p+" 
"+ex.getMessage());
             }
         }
 
-        private static String argString(Resource r, Property p, String 
dftValue) {
-            try { GraphUtils.atmostOneProperty(r, p); }
-            catch (NotUniqueException ex) {
-                throw new FusekiConfigException(ex.getMessage());
-            }
-            Statement stmt = r.getProperty(p);
-            if ( stmt == null )
-                return dftValue;
+        private static String argString(Graph graph, Node r, Node p, String 
dftValue) {
             try {
-                Node n = stmt.getObject().asLiteral().asNode();
-                if ( ! G.isString(n) )
-                    throw new FusekiConfigException("Not a string for '"+p+"' 
: "+stmt.getObject());
-                return n.getLiteralLexicalForm();
-            } catch (JenaException ex) {
-                throw new FusekiConfigException("Not a string for '"+p+"' : 
"+stmt.getObject());
+                String str = getAsString(graph, r, p);
+                if ( str == null )
+                    return dftValue;
+                return str;
+            } catch (RDFDataException ex) {
+                throw new FusekiConfigException("String argument "+r+" "+p+" 
"+ex.getMessage());
             }
         }
 
+        /** URI or xsd:string as java string. **/
+        private static String getAsString(Graph config, Node server, Node 
property) {
+            Node n = G.getZeroOrOneSP(config, server, property);
+            if ( n == null )
+                return null;
+            if ( n.isURI() )
+                return n.getURI();
+            if ( G.isString(n) )
+                return G.asString(n);
+            throw new FusekiConfigException("Not a URI or a string");
+        }
+
+        private static Boolean getAsBoolean(Graph config, Node server, Node 
property) {
+            Node n = G.getZeroOrOneSP(config, server, property);
+            if ( n == null )
+                return null;
+            if ( G.isBoolean(n) ) {
+                return G.asBoolean(n);
+            }
+            throw new FusekiConfigException("Not a boolean");
+        }
 
         /**
          * Choose the HTTP authentication scheme.
diff --git 
a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestAuthorized.java
 
b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestAuthorized.java
index 4b436e5652..752e4a08c4 100644
--- 
a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestAuthorized.java
+++ 
b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/access/TestAuthorized.java
@@ -23,19 +23,21 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import org.junit.Test;
+
 import org.apache.jena.atlas.logging.LogCtl;
 import org.apache.jena.fuseki.Fuseki;
 import org.apache.jena.fuseki.auth.Auth;
 import org.apache.jena.fuseki.auth.AuthPolicy;
 import org.apache.jena.fuseki.build.FusekiConfig;
-import org.apache.jena.rdf.model.Model;
-import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.graph.Graph;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.NodeFactory;
 import org.apache.jena.riot.RDFDataMgr;
-import org.junit.Test;
 
 public class TestAuthorized {
 
-    static Model model = 
RDFDataMgr.loadModel("testing/Access/allowedUsers.ttl");
+    private static Graph allowedUsersGraph = 
RDFDataMgr.loadGraph("testing/Access/allowedUsers.ttl");
 
     @Test public void auth_anon() {
         AuthPolicy auth = Auth.ANY_ANON;
@@ -89,21 +91,25 @@ public class TestAuthorized {
         assertFalse(auth.isAllowed("user3"));
     }
 
+    private static Node node(String uri) {
+        return NodeFactory.createURI(uri);
+    }
+
     @Test public void auth_parse_no_info_1() {
-        Resource r = model.createResource("http://example/notInData";);
-        AuthPolicy auth = FusekiConfig.allowedUsers(r);
+        Node r = node("<http://example/notInData>");
+        AuthPolicy auth = FusekiConfig.allowedUsers(allowedUsersGraph, r);
         assertNull(auth);
     }
 
     @Test public void auth_parse_no_info_2() {
-        Resource r = model.createResource("http://example/none";);
-        AuthPolicy auth = FusekiConfig.allowedUsers(r);
+        Node r = node("http://example/none";);
+        AuthPolicy auth = FusekiConfig.allowedUsers(allowedUsersGraph, r);
         assertNull(auth);
     }
 
     @Test public void auth_parse_1() {
-        Resource r = model.createResource("http://example/r1";);
-        AuthPolicy auth = FusekiConfig.allowedUsers(r);
+        Node r = node("http://example/r1";);
+        AuthPolicy auth = FusekiConfig.allowedUsers(allowedUsersGraph, r);
         assertNotNull(auth);
         assertFalse(auth.isAllowed(null));
         assertTrue(auth.isAllowed("user1"));
@@ -112,8 +118,8 @@ public class TestAuthorized {
     }
 
     @Test public void auth_parse_2() {
-        Resource r = model.createResource("http://example/r2";);
-        AuthPolicy auth = FusekiConfig.allowedUsers(r);
+        Node r = node("http://example/r2";);
+        AuthPolicy auth = FusekiConfig.allowedUsers(allowedUsersGraph, r);
         assertNotNull(auth);
         assertFalse(auth.isAllowed(null));
         assertTrue(auth.isAllowed("user1"));
@@ -122,8 +128,8 @@ public class TestAuthorized {
     }
 
     @Test public void auth_parse_loggedIn() {
-        Resource r = model.createResource("http://example/rLoggedIn";);
-        AuthPolicy auth = FusekiConfig.allowedUsers(r);
+        Node r = node("http://example/rLoggedIn";);
+        AuthPolicy auth = FusekiConfig.allowedUsers(allowedUsersGraph, r);
         assertNotNull(auth);
         assertFalse(auth.isAllowed(null));
         assertTrue(auth.isAllowed("user1"));
diff --git 
a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
 
b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
index ce4f319ad3..109332f8ad 100644
--- 
a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
+++ 
b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/mgt/ActionDatasets.java
@@ -197,8 +197,7 @@ public class ActionDatasets extends ActionContainerItem {
                     RDFDataMgr.write(outCopy, modelData, Lang.TURTLE);
                 }
 
-                // Need to be in Resource space at this point.
-                DataAccessPoint dataAccessPoint = 
FusekiConfig.buildDataAccessPoint(subject, registry);
+                DataAccessPoint dataAccessPoint = 
FusekiConfig.buildDataAccessPoint(subject.getModel().getGraph(), 
subject.asNode(), registry);
                 if ( dataAccessPoint == null ) {
                     FmtLog.error(action.log, "Failed to build DataAccessPoint: 
datasetPath = %s; DataAccessPoint name = %s", datasetPath, dataAccessPoint);
                     ServletOps.errorBadRequest("Failed to build 
DataAccessPoint");
diff --git 
a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/webapp/FusekiWebapp.java
 
b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/webapp/FusekiWebapp.java
index 19ae12803b..cfe6d69731 100644
--- 
a/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/webapp/FusekiWebapp.java
+++ 
b/jena-fuseki2/jena-fuseki-webapp/src/main/java/org/apache/jena/fuseki/webapp/FusekiWebapp.java
@@ -37,7 +37,6 @@ import org.apache.jena.cmd.CmdException;
 import org.apache.jena.dboe.sys.Names;
 import org.apache.jena.fuseki.Fuseki;
 import org.apache.jena.fuseki.FusekiConfigException;
-import org.apache.jena.fuseki.build.DatasetDescriptionMap;
 import org.apache.jena.fuseki.build.FusekiConfig;
 import org.apache.jena.fuseki.cmd.FusekiArgs;
 import org.apache.jena.fuseki.mgt.Template;
@@ -282,7 +281,6 @@ public class FusekiWebapp
 
     private static DataAccessPoint configFromTemplate(String templateFile, 
String datasetPath,
                                                       boolean allowUpdate, 
Map<String, String> params) {
-        DatasetDescriptionMap registry = new DatasetDescriptionMap();
         // ---- Setup
         if ( params == null ) {
             params = new HashMap<>();
@@ -311,7 +309,7 @@ public class FusekiWebapp
         Lang lang = RDFLanguages.filenameToLang(templateFile, Lang.TTL);
         Model model = RDFParser.fromString(str, 
lang).base(datasetPath).toModel();
 
-        List<DataAccessPoint> defns = FusekiConfig.servicesAndDatasets(model);
+        List<DataAccessPoint> defns = 
FusekiConfig.servicesAndDatasets(model.getGraph());
         if ( defns.size() != 1 ) {
             if ( defns.isEmpty() )
                 ServletOps.errorBadRequest("No description of a Fuseki 
service");
diff --git 
a/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestBuilder.java
 
b/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestBuilder.java
index 334acb74cc..14d7a995d0 100644
--- 
a/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestBuilder.java
+++ 
b/jena-fuseki2/jena-fuseki-webapp/src/test/java/org/apache/jena/fuseki/TestBuilder.java
@@ -21,15 +21,16 @@ package org.apache.jena.fuseki;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 
+import org.junit.Test;
+
 import org.apache.jena.fuseki.build.DatasetDescriptionMap;
 import org.apache.jena.fuseki.build.FusekiConfig;
-import org.apache.jena.query.Dataset;
 import org.apache.jena.rdf.model.Model;
 import org.apache.jena.rdf.model.ModelFactory;
 import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.sparql.core.DatasetGraph;
 import org.apache.jena.tdb1.assembler.VocabTDB1;
 import org.apache.jena.vocabulary.RDF;
-import org.junit.Test;
 
 public class TestBuilder {
 
@@ -49,17 +50,17 @@ public class TestBuilder {
     }
     @Test
     public void testVerifySameDatasetObjectForSameDescription() {
-
-        Dataset ds1 = FusekiConfig.getDataset(dsDesc1, registry);
-        Dataset ds2 = FusekiConfig.getDataset(dsDesc1, registry);
+        DatasetDescriptionMap registry = new DatasetDescriptionMap();
+        DatasetGraph ds1 = 
FusekiConfig.getDataset(dsDesc1.getModel().getGraph(), dsDesc1.asNode(), 
registry);
+        DatasetGraph ds2 = 
FusekiConfig.getDataset(dsDesc1.getModel().getGraph(), dsDesc1.asNode(), 
registry);
         assertEquals(ds1, ds2);
     }
 
     @Test
     public void testVerifyDifferentDatasetObjectsForDifferentDescriptions() {
-
-        Dataset ds1 = FusekiConfig.getDataset(dsDesc1, registry);
-        Dataset ds2 = FusekiConfig.getDataset(dsDesc2, registry);
+        DatasetDescriptionMap registry = new DatasetDescriptionMap();
+        DatasetGraph ds1 = 
FusekiConfig.getDataset(dsDesc1.getModel().getGraph(), dsDesc1.asNode(), 
registry);
+        DatasetGraph ds2 = 
FusekiConfig.getDataset(dsDesc2.getModel().getGraph(), dsDesc2.asNode(), 
registry);
         assertNotEquals(ds1, ds2);
     }
 }

Reply via email to