diff --git a/jena-arq/src/main/java/org/apache/jena/riot/other/G.java b/jena-arq/src/main/java/org/apache/jena/riot/other/G.java new file mode 100644 index 00000000000..a4d846cc1ae --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/riot/other/G.java @@ -0,0 +1,671 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.riot.other; + +import java.util.*; +import java.util.function.Consumer; + +import org.apache.jena.atlas.iterator.Iter; +import org.apache.jena.graph.*; +import org.apache.jena.riot.out.NodeFmtLib; +import org.apache.jena.sparql.core.Quad; +import org.apache.jena.sparql.graph.NodeConst; +import org.apache.jena.sparql.util.graph.GNode; +import org.apache.jena.sparql.util.graph.GraphList; +import org.apache.jena.util.iterator.ExtendedIterator; + +/** A library of functions for working with {@link Graph}. */ +public class G { + private G() {} + + private static Node rdfType = NodeConst.nodeRDFType; + + /** Return the subject of a triple, or null if the triple is null. */ + public static Node subject(Triple triple) { + return triple == null ? null : triple.getSubject(); + } + + /** Return the predicate of a triple, or null if the triple is null. */ + public static Node predicate(Triple triple) { + return triple == null ? null : triple.getPredicate(); + } + + /** Return the object of a triple, or null if the triple is null. */ + public static Node object(Triple triple) { + return triple == null ? null : triple.getObject(); + } + + // ---- Node filter tests. + public static boolean isURI(Node n) { return n != null && n.isURI(); } + public static boolean isBlank(Node n) { return n != null && n.isBlank(); } + public static boolean isLiteral(Node n) { return n != null && n.isLiteral(); } + public static boolean isResource(Node n) { return n != null && (n.isURI()||n.isBlank()); } + public static boolean isNodeTriple(Node n) { return n != null && n.isNodeTriple(); } + public static boolean isNodeGraph(Node n) { return n != null && n.isNodeGraph(); } + + /** Convert null to Node.ANY */ + public static Node nullAsAny(Node x) { return nullAsDft(x, Node.ANY) ; } + + /** Convert null to some default Node */ + public static Node nullAsDft(Node x, Node dft) { return x==null ? dft : x ; } + + /** Does the graph match the s/p/o pattern? */ + public static boolean contains(Graph graph, Node subject, Node predicate, Node object) { + Objects.requireNonNull(graph, "graph"); + return graph.contains(subject, predicate, object); + } + + /** Does the graph use the node anywhere as a subject, predicate or object? */ + public static boolean containsNode(Graph graph, Node node) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(node, "node"); + return GraphUtil.containsNode(graph, node); +// return +// contains(graph, node, Node.ANY, Node.ANY) || +// contains(graph, Node.ANY, Node.ANY, node) || +// contains(graph, Node.ANY, node, Node.ANY) ; + } + + /** Test whether the node has the type or is rdfs:subclassOf. */ + public static boolean isOfType(Graph graph, Node node, Node type) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(node, "node"); + Objects.requireNonNull(type, "type"); + List allClasses = listSubClasses(graph, type); + for ( Node c : allClasses ) { + if ( hasType(graph, node, c) ) + return true; + } + return false; + } + + /** Does the node x have the given type (non-RDFS - no rdfs:subclassOf considered)? */ + public static boolean hasType(Graph graph, Node node, Node type) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(node, "node"); + Objects.requireNonNull(type, "type"); + return contains(graph, node, NodeConst.nodeRDFType, type); + } + + //---- get/list/iter + + /** Does node {@code s} have property {@code p} in graph {@code g}? */ + public static boolean hasProperty(Graph graph, Node subject, Node predicate) { + Objects.requireNonNull(graph, "graph"); + return graph.contains(subject, predicate, null); + } + + /** Contains exactly one. */ + public static boolean containsOne(Graph graph, Node subject, Node predicate, Node object) { + Objects.requireNonNull(graph, "graph"); + ExtendedIterator iter = graph.find(subject, predicate, object); + try { + if ( ! iter.hasNext() ) + return false; + iter.next(); + return !iter.hasNext(); + } finally { iter.close(); } + } + + /** + * Get object, given subject and predicate. Returns one (non-deterministically) or null. + * See also {@link #getOneSP} and {@link #getZeroOrOneSP}. + */ + public static Node getSP(Graph graph, Node subject, Node predicate) { + Objects.requireNonNull(graph, "graph"); + return object(first(find(graph, subject, predicate, Node.ANY))); + } + + // --- Graph walking. + + /** + * Get object for subject-predicate. Must be exactly one object; exception + * {@linkplain RDFDataException} thrown when none or more than one. + */ + public static Node getOneSP(Graph graph, Node subject, Node predicate) { + Objects.requireNonNull(graph, "graph"); + return object(findUnique(graph, subject, predicate, Node.ANY)); + } + + /** + * Get object for subject-predicate. Return null for none, object for one, and + * exception {@linkplain RDFDataException} if more than one. + */ + public static Node getZeroOrOneSP(Graph graph, Node subject, Node predicate) { + Objects.requireNonNull(graph, "graph"); + return object(findZeroOne(graph, subject, predicate, Node.ANY)); + } + + /** + * Get the subject, given predicate and object. Returns one (non-deterministically) or null. + * See also {@link #getOnePO} and {@link #getZeroOrOnePO}. + */ + public static Node getPO(Graph graph, Node predicate, Node object) { + Objects.requireNonNull(graph, "graph"); + return object(first(find(graph, Node.ANY, predicate, object))); + } + + /** + * Get the subject for predicate-object. Must be exactly one subject; exception + * {@linkplain RDFDataException} thrown when none or more than one. + */ + public static Node getOnePO(Graph graph, Node predicate, Node object) { + Objects.requireNonNull(graph, "graph"); + return subject(findUnique(graph, Node.ANY, predicate, object)); + } + + /** + * Get the subject for predicate-object. Return null for none, subject for one, throw + * exception {@linkplain RDFDataException} if more than one. + */ + public static Node getZeroOrOnePO(Graph graph, Node predicate, Node object) { + Objects.requireNonNull(graph, "graph"); + return subject(findZeroOne(graph, Node.ANY, predicate, object)); + } + + /** + * Get triple if there is exactly one to match the s/p/o, else throw + * {@linkplain RDFDataException}. + */ + public static Triple getOne(Graph graph, Node subject, Node predicate, Node object) { + Objects.requireNonNull(graph, "graph"); + return findUnique(graph, subject, predicate, object); + } + + /** + * Get triple if there is exactly one to match the s/p/o; return null if none; + * throw {@linkplain RDFDataException} if more than one. + */ + public static Triple getZeroOrOne(Graph graph, Node subject, Node predicate, Node object) { + Objects.requireNonNull(graph, "graph"); + return findZeroOne(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 + * used or explicitly closed. It is preferable use {@link #listSP} which handles + * this condition. + */ + public static ExtendedIterator iterSP(Graph graph, Node subject, Node predicate) { + Objects.requireNonNull(graph, "graph"); + return find(graph, subject, predicate, null).mapWith(Triple::getObject); + } + + /** + * List of objects matching the subject-predicate (which can be wildcards). + */ + public static List listSP(Graph graph, Node subject, Node predicate) { + Objects.requireNonNull(graph, "graph"); + return iterSP(graph, subject, predicate).toList(); + } + + /** Count matches of subject-predicate (which can be wildcards). */ + public static long countSP(Graph graph, Node subject, Node predicate) { + Objects.requireNonNull(graph, "graph"); + return Iter.count(iterSP(graph, subject, predicate)); + } + + /** + * {@link ExtendedIterator} of subjects where the triple matches for predicate + * and object (which can be wildcards). The {@link ExtendedIterator} must be + * fully used or explicitly closed. It is preferable use {@link #listSP} which + * handles this condition. + */ + public static ExtendedIterator iterPO(Graph graph, Node predicate, Node object) { + Objects.requireNonNull(graph, "graph"); + return find(graph, null, predicate, object).mapWith(Triple::getSubject); + } + + /** + * List of subjects matching the predicate-object (which can be wildcards). + */ + public static List listPO(Graph graph, Node predicate, Node object) { + Objects.requireNonNull(graph, "graph"); + return iterPO(graph, predicate, object).toList(); + } + + /** Count matches of predicate-object (which can be wildcards). */ + public static long countPO(Graph graph, Node predicate, Node object) { + Objects.requireNonNull(graph, "graph"); + return Iter.count(iterPO(graph, predicate, object)); + } + + // DISTINCT means these are space using. + + /** List the subjects in a graph (no duplicates) */ + public static Iterator listSubjects(Graph graph) { + Objects.requireNonNull(graph, "graph"); + ExtendedIterator iter = graph.find(Node.ANY, Node.ANY, Node.ANY); + return Iter.iter(iter).map(Triple::getSubject).distinct(); + } + + /** List the predicates in a graph (no duplicates) */ + public static Iterator listPredicates(Graph graph) { + Objects.requireNonNull(graph, "graph"); + ExtendedIterator iter = graph.find(Node.ANY, Node.ANY, Node.ANY); + return Iter.iter(iter).map(Triple::getPredicate).distinct(); + } + + /** List the objects in a graph (no duplicates) */ + public static Iterator listObjects(Graph graph) { + Objects.requireNonNull(graph, "graph"); + ExtendedIterator iter = graph.find(Node.ANY, Node.ANY, Node.ANY); + return Iter.iter(iter).map(Triple::getObject).distinct(); + } + + // ---- rdf:type, not RDFS + + /** + * List the subjects with exactly {@code type}. + * See {@link #listNodesOfTypeRDFS(Graph, Node)}, which does include sub-classes. + */ + public static List nodesOfTypeAsList(Graph graph, Node type) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(type, "type"); + return find(graph, null, rdfType, type).mapWith(Triple::getSubject).toList(); + } + + /** + * List the types of a node/subject. + * See {@link #listTypesOfNodeRDFS(Graph, Node)} , which does include super-classes. + */ + public static List typesOfNodeAsList(Graph graph, Node node) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(node, "node"); + return find(graph, node, rdfType, null).mapWith(Triple::getObject).toList(); + } + + /** + * Set of nodes with exactly {@code type}. + * See {@link #allNodesOfTypeRDFS(Graph, Node)}, which does include sub-classes. + */ + public static Set nodesOfTypeAsSet(Graph graph, Node type) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(type, "type"); + return find(graph, null, rdfType, type).mapWith(Triple::getSubject).toSet(); + } + + /** + * Set of exact types of a node See {@link #allTypesOfNodeRDFS(Graph, Node)}, + * which does include super-classes. + */ + public static Set typesOfNodeAsSet(Graph graph, Node node) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(node, "node"); + return find(graph, node, rdfType, null).mapWith(Triple::getObject).toSet(); + } + + // ---- RDF list. + + /** Return a java list for an RDF list of data. */ + public static List rdfList(Graph graph, Node node) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(node, "node"); + GNode gNode = GNode.create(graph, node); + return GraphList.members(gNode); + } + + // Sub-class / super-class + + /** + * List the subclasses of a type, including itself. + * This is ?x rdfs:subClassOf* type. + * The list does not contain duplicates. + */ + public static List listSubClasses(Graph graph, Node type) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(type, "type"); + List acc = new ArrayList<>(); + // Subclasses are follow rdfs:subClassOf in reverse - object to subject. + // Transitive.transitive is "visit once". + Transitive.transitiveInc(graph, false, type, NodeConst.rdfsSubclassOf, acc); + return acc; + } + + /** + * List the super-classes of a type, including itself. + * This is type rdfs:subClassOf* ?x. + * The list does not contain duplicates. + */ + public static List listSuperClasses(Graph graph, Node type) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(type, "type"); + List acc = new ArrayList<>(); + // Super classes are "follow rdfs:subclassOf" - subject to object. + // Transitive.transitive is "visit once". + Transitive.transitiveInc(graph, true, type, NodeConst.rdfsSubclassOf, acc); + return acc; + } + + /** + * Set of the subclasses of a type, including itself. + * This is ?x rdfs:subClassOf* type. + */ + public static Set subClasses(Graph graph, Node type) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(type, "type"); + Set acc = new HashSet<>(); + // Subclasses are follow rdfs:subclassOf in reverse - object to subject. + Transitive.transitiveInc(graph, false, type, NodeConst.rdfsSubclassOf, acc); + return acc; + } + + /** + * Set of the subclasses of a type, including itself. + * This is ?x rdfs:subClassOf* type. + */ + public static Set superClasses(Graph graph, Node type) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(type, "type"); + Set acc = new HashSet<>(); + Transitive.transitiveInc(graph, true, type, NodeConst.rdfsSubclassOf, acc); + return acc; + } + + // ---- RDFS + + /** + * List the types of a node, following rdfs:subClassOf for super classes. + */ + public static List listTypesOfNodeRDFS(Graph graph, Node node) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(node, "node"); + List types = typesOfNodeAsList(graph, node); + List types2 = new ArrayList<>(); + types.forEach(t->{ + List subClasses = listSuperClasses(graph, t); + types2.addAll(subClasses); + }); + return types2; + } + + /** + * List all the nodes of type, including node of sub-classes. + */ + public static List listNodesOfTypeRDFS(Graph graph, Node type) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(type, "type"); + List types = listSubClasses(graph, type); + List nodes = new ArrayList<>(); + accNodesOfTypes(nodes, graph, types); + return nodes; + } + + /** + * List all the types of a node, including super-classes. + */ + public static Set allTypesOfNodeRDFS(Graph graph, Node node) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(node, "node"); + Set types = typesOfNodeAsSet(graph, node); + Set types2 = new HashSet<>(); + types.forEach(t->{ + List subClasses = listSuperClasses(graph, t); + types2.addAll(subClasses); + }); + return types2; + } + + /** List all the node of type, including considering rdfs:subClassOf */ + public static Set allNodesOfTypeRDFS(Graph graph, Node type) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(type, "type"); + Set types = subClasses(graph, type); + Set nodes = new HashSet<>(); + accNodesOfTypes(nodes, graph, types); + return nodes; + } + + /** For each type, find nodes of that type and accumulate */ + private static void accNodesOfTypes(Collection acc, Graph graph, Collection types) { + types.forEach(t-> + find(graph, null, rdfType, t).mapWith(Triple::getSubject).forEach(acc::add) + ); + } + + /** Return a set of all objects for subject-predicate */ + public static Set allSP(Graph graph, Node subject, Node predicate) { + Objects.requireNonNull(graph, "graph"); + return find(graph, subject, predicate, null).mapWith(Triple::getObject).toSet(); + } + + /** Return a set of all subjects for predicate-object */ + public static Set allPO(Graph graph, Node predicate, Node object) { + Objects.requireNonNull(graph, "graph"); + return find(graph, null, predicate, object).mapWith(Triple::getSubject).toSet(); + } + + // --- Graph walking. + + /** Count the number of in-arc to an object */ + public static long objectConnectiveness(Graph graph, Node object) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(object, "object"); + return Iter.count(find(graph, null, null, object)); + } + + /** Test whether an object has exactly one in-arc. */ + public static boolean oneConnected(Graph graph, Node object) { + Objects.requireNonNull(graph, "graph"); + Objects.requireNonNull(object, "object"); + ExtendedIterator iter = find(graph, null, null, object); + try { + if ( ! iter.hasNext() ) + // Zero. + return false; + iter.next(); + if ( iter.hasNext() ) + // more than one + return false; + return true; + } finally { iter.close(); } + } + + /** {@link Graph#find(Node, Node, Node)} as a function. */ + public static ExtendedIterator find(Graph graph, Node subject, Node predicate, Node object) { + Objects.requireNonNull(graph, "graph"); + return graph.find(subject, predicate, object); + } + + /** {@link Graph#find()} as a function. */ + public static ExtendedIterator findAll(Graph graph) { + Objects.requireNonNull(graph, "graph"); + return graph.find(); + } + + private static Triple findUnique(Graph graph, Node subject, Node predicate, Node object) { + ExtendedIterator iter = graph.find(subject, predicate, object); + try { + if ( ! iter.hasNext() ) + throw new RDFDataException("No match : "+matchStr(subject, predicate, object)); + Triple x = iter.next(); + if ( iter.hasNext() ) + throw new RDFDataException("More than one match : "+matchStr(subject, predicate, object)); + return x; + } finally { iter.close(); } + } + + private static Triple findZeroOne(Graph graph, Node subject, Node predicate, Node object) { + ExtendedIterator iter = graph.find(subject, predicate, object); + try { + if ( ! iter.hasNext() ) + return null; + Triple x = iter.next(); + if ( iter.hasNext() ) + throw new RDFDataException("More than one match : "+matchStr(subject, predicate, object)); + return x; + } finally { iter.close(); } + } + + private static String matchStr(Node subject, Node predicate, Node object) { + return "("+NodeFmtLib.strNodes(subject, predicate, object)+")"; + } + + private static Triple first(ExtendedIterator iter) { + try { + if ( ! iter.hasNext() ) + return null; + return iter.next(); + } finally { iter.close(); } + } + + /** Are all the arguments non-null? */ + @SafeVarargs + public static boolean allNonNull(X ... objects) { + return countNonNulls(objects) == objects.length; + } + + /** Is one and only one argument non-null? */ + @SafeVarargs + public static boolean exactlyOneSet(X ... objects) { + return countNonNulls(objects) == 1; + } + + /** Is one or none of the arguments non-null? */ + @SafeVarargs + public static X atMostOne(X ... objects) { + int c = 0; + X x = null; + for ( X obj : objects ) { + if ( obj != null ) { + c++; + if ( c > 1 ) + throw new RDFDataException("atMostOne:"+Arrays.asList(objects)); + if ( x == null ) + x = obj; + } + } + return x; + } + + /** Count non-nulls */ + @SafeVarargs + public static int countNonNulls(X ... objects) { + int x = 0; + for ( Object obj : objects ) { + if ( obj != null ) + x++; + } + return x; + } + + // ---- Project + + /** Project quads to triples */ + public static Iter quads2triples(Iterator iter) + { return Iter.iter(iter).map(Quad::asTriple); } + + /** Project quad to graph name */ + public static Iterator quad2graphName(Iterator iter) + { return Iter.map(iter, Quad::getGraph) ; } + + /** Project quad to subject */ + public static Iterator quad2subject(Iterator iter) + { return Iter.map(iter, Quad::getSubject) ; } + + /** Project quad to predicate */ + public static Iterator quad2predicate(Iterator iter) + { return Iter.map(iter, Quad::getPredicate) ; } + + /** Project quad to object */ + public static Iterator quad2object(Iterator iter) + { return Iter.map(iter, Quad::getObject) ; } + + /** Project triple to subject */ + public static Iterator triple2subject(Iterator iter) + { return Iter.map(iter, Triple::getSubject) ; } + + /** Project triple to predicate */ + public static Iterator triple2predicate(Iterator iter) + { return Iter.map(iter, Triple::getPredicate) ; } + + /** Project triple to object */ + public static Iterator triple2object(Iterator iter) + { return Iter.map(iter, Triple::getObject) ; } + + // Graph operations. + + /** + * Add src to dst - assumes transaction. + * src and dst must not overlap. + * Copies "left to right" -- {@code src into dst} + * @param src + * @param dst + */ + public static void copyGraphSrcToDst(Graph src, Graph dst) { + apply(src, dst::add); + } + + /** + * Clear graph. + */ + public static void clear(Graph graph) { + graph.clear(); + } + + /** + * Apply an action to every triple of a graph. The action must not attempt to + * modify the graph but it can read it. + */ + public static void apply(Graph src, Consumer action) { + ExtendedIterator iter = src.find(); + apply(iter, action); + } + + /** + * Apply an action to every triple of an iterator. + * If the iterator is attracted to a graph, the action must not attempt to + * modify the graph but it can read it. + */ + public static void apply(ExtendedIterator iter, Consumer action) { + try { + while(iter.hasNext()) { + Triple t = iter.next(); + action.accept(t); + } + } finally { iter.close(); } + } + + /** + * Delete triples in the graph-to-modify (arg 1) that are in the source (arg 2). + * @param modify + * @param srcGraph + */ + public static void deleteModify(Graph modify, Graph srcGraph) { + // NB order of arguments. + GraphUtil.deleteFrom(modify, srcGraph); + } + + /** Convert an iterator of triples into quads for the specified graph name. */ + public static Iter triples2quads(Node graphNode, Iterator iter) { + return Iter.iter(iter).map(t -> new Quad(graphNode, t)) ; + } + + /** + * Convert an iterator of triples into quads for the default graph. This is + * {@link Quad#defaultGraphIRI}, not {@link Quad#defaultGraphNodeGenerated}, which is + * for quads outside a dataset, usually the output of parsers. + */ + public static Iter triples2quadsDftGraph(Iterator iter) { + return triples2quads(Quad.defaultGraphIRI, iter) ; + } +} diff --git a/jena-arq/src/main/java/org/apache/jena/riot/other/GLib.java b/jena-arq/src/main/java/org/apache/jena/riot/other/GLib.java deleted file mode 100644 index db147244779..00000000000 --- a/jena-arq/src/main/java/org/apache/jena/riot/other/GLib.java +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.jena.riot.other; - -import java.util.Iterator ; -import org.apache.jena.atlas.iterator.Iter ; -import org.apache.jena.graph.Graph ; -import org.apache.jena.graph.Node ; -import org.apache.jena.graph.Triple ; -import org.apache.jena.sparql.core.Quad ; -import org.apache.jena.util.iterator.ExtendedIterator ; - -/** A collection of Graph/Triple/Node related functions */ -public class GLib -{ - /** Convert null to Node.ANY */ - public static Node nullAsAny(Node x) { return nullAsDft(x, Node.ANY) ; } - - /** Convert null to some default Node */ - public static Node nullAsDft(Node x, Node dft) { return x==null ? dft : x ; } - - // DISTINCT means these are space using. - /** List the subjects in a graph (no duplicates) */ - public static Iterator listSubjects(Graph graph) - { - ExtendedIterator iter = graph.find(Node.ANY, Node.ANY, Node.ANY) ; - return Iter.iter(iter).map(Triple::getSubject).distinct() ; - } - - /** List the predicates in a graph (no duplicates) */ - public static Iterator listPredicates(Graph graph) - { - ExtendedIterator iter = graph.find(Node.ANY, Node.ANY, Node.ANY) ; - return Iter.iter(iter).map(Triple::getPredicate).distinct() ; - } - - /** List the objects in a graph (no duplicates) */ - public static Iterator listObjects(Graph graph) - { - ExtendedIterator iter = graph.find(Node.ANY, Node.ANY, Node.ANY) ; - return Iter.iter(iter).map(Triple::getObject).distinct() ; - } - - /** Project quads to triples */ - public static Iter quads2triples(Iterator iter) - { - return Iter.iter(iter).map(Quad::asTriple) ; - } - - /** Project quad to graphname */ - public static Iterator quad2graphName(Iterator iter) - { return Iter.map(iter, Quad::getGraph) ; } - - /** Project quad to graphname */ - public static Iterator quad2subject(Iterator iter) - { return Iter.map(iter, Quad::getSubject) ; } - - /** Project quad to predicate */ - public static Iterator quad2predicate(Iterator iter) - { return Iter.map(iter, Quad::getPredicate) ; } - - /** Project quad to object */ - public static Iterator quad2object(Iterator iter) - { return Iter.map(iter, Quad::getObject) ; } - - /** Project triple to subject */ - public static Iterator triple2subject(Iterator iter) - { return Iter.map(iter, Triple::getSubject) ; } - - /** Project triple to predicate */ - public static Iterator triple2predicate(Iterator iter) - { return Iter.map(iter, Triple::getPredicate) ; } - - /** Project triple to object */ - public static Iterator triple2object(Iterator iter) - { return Iter.map(iter, Triple::getObject) ; } -} - diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/lib/RDFDataException.java b/jena-arq/src/main/java/org/apache/jena/riot/other/RDFDataException.java similarity index 87% rename from jena-shacl/src/main/java/org/apache/jena/shacl/lib/RDFDataException.java rename to jena-arq/src/main/java/org/apache/jena/riot/other/RDFDataException.java index 8dce82faf05..bbf656e6d63 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/lib/RDFDataException.java +++ b/jena-arq/src/main/java/org/apache/jena/riot/other/RDFDataException.java @@ -16,11 +16,11 @@ * limitations under the License. */ -package org.apache.jena.shacl.lib; +package org.apache.jena.riot.other; -import org.apache.jena.shacl.ShaclException; +import org.apache.jena.shared.JenaException; -public class RDFDataException extends ShaclException { +public class RDFDataException extends JenaException { public RDFDataException(String msg) { super(msg);} public RDFDataException(String msg, Throwable th) { super(msg, th); } } diff --git a/jena-arq/src/main/java/org/apache/jena/riot/other/Transitive.java b/jena-arq/src/main/java/org/apache/jena/riot/other/Transitive.java new file mode 100644 index 00000000000..50f1d1816d2 --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/riot/other/Transitive.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jena.riot.other; + +import java.util.*; + +import org.apache.jena.graph.Graph; +import org.apache.jena.graph.Node; +import org.apache.jena.graph.Triple; +import org.apache.jena.util.iterator.ExtendedIterator; + +public class Transitive { + // GLib. + + // (?x :p ?z) <- (?x :p ?y) (?y :p ?z) + + /** + * Calculate the transitive closure of a property. + * + * Returns a map of node to all reachable nodes. + */ + public static Map> transitive(Graph graph, Node property) { + //Test against c.f. "SELECT ?x ?y { ?x property ?y }" + + Map> reachable = new HashMap<>(); + ExtendedIterator props = G.find(graph, null, property, null); + // Old school loop. + try { + for ( ; props.hasNext() ; ) { + Triple triple = props.next(); + Node node = triple.getSubject(); + if ( ! reachable.containsKey(node) ) { + // Does not take advantage of intermediate results. + // Given cycles, that isn't so easy as it would be if it were a tree. + Collection subs = new HashSet<>(); + transitiveExc(graph, true, node, property, subs); + reachable.put(node, subs); + } + } + } finally { props.close(); } + return reachable; + } + + /** + * Transitive closure of a property from a start node, and including the start node. + */ + public static void transitiveInc(Graph graph, boolean forward, Node node, Node predicate, Collection output) { + Set visited = new HashSet<>(); + recurse(graph, forward, 0, -1, node, predicate, visited, output); + } + + /** + * Transitive closure of a property from a start node, excluding the start node unless reachable via a cycle. + */ + public static void transitiveExc(Graph graph, boolean forward, Node node, Node predicate, Collection output) { + ExtendedIterator iter = singleStep(graph, forward, node, predicate); + try { + Set visited = new HashSet<>(); + for (; iter.hasNext();) { + Node n1 = iter.next() ; + recurse(graph, forward, 1, -1, n1, predicate, visited, output) ; + } + } finally { iter.close(); } + } + + private static void recurse(Graph graph, boolean forward, int stepCount, int maxStepCount, Node node, Node predicate, Set visited, Collection output) { + if ( maxStepCount >= 0 && stepCount > maxStepCount ) + return ; + if ( !visited.add(node) ) + return ; + output.add(node); + ExtendedIterator iter1 = singleStep(graph, forward, node, predicate) ; + try { + // For each step, add to results and recurse. + for (; iter1.hasNext();) { + Node n1 = iter1.next() ; + recurse(graph, forward, stepCount + 1, maxStepCount, n1, predicate, visited, output) ; + } + } finally { iter1.close(); } + } + + // A single step of a transitive properties. + // Because for SP? or ?PO, no duplicates occur, so works for both strategies. + static ExtendedIterator singleStep(Graph graph, boolean forward, Node node, Node property) { + if ( forward ) + return G.find(graph, node, property, Node.ANY).mapWith(Triple::getObject); + else + return G.find(graph, Node.ANY, property, node).mapWith(Triple::getSubject); + } +} diff --git a/jena-arq/src/main/java/org/apache/jena/riot/process/normalize/NormalizeValue.java b/jena-arq/src/main/java/org/apache/jena/riot/process/normalize/NormalizeValue.java index 1da8547db58..52ba05a4813 100644 --- a/jena-arq/src/main/java/org/apache/jena/riot/process/normalize/NormalizeValue.java +++ b/jena-arq/src/main/java/org/apache/jena/riot/process/normalize/NormalizeValue.java @@ -44,7 +44,7 @@ class NormalizeValue // hexBinary, base64Binary. // Auxillary class of datatype handers, placed here to avoid static initialization - // ordering problems (if in CanonicalizeLiteral, all this low-level machinary would + // ordering problems (if in CanonicalizeLiteral, all this low-level machinery would // need to be in the file before the external API, which I consider bad style). It // is a source of obscure bugs. diff --git a/jena-arq/src/main/java/org/apache/jena/riot/writer/JsonLDWriter.java b/jena-arq/src/main/java/org/apache/jena/riot/writer/JsonLDWriter.java index 6a6f8883181..26c7ed12b1d 100644 --- a/jena-arq/src/main/java/org/apache/jena/riot/writer/JsonLDWriter.java +++ b/jena-arq/src/main/java/org/apache/jena/riot/writer/JsonLDWriter.java @@ -305,45 +305,42 @@ private static Object createJsonldContext(Graph g, PrefixMap prefixMap, boolean /** Add properties to jsonld context. */ static void addProperties(Map ctx, Graph g) { - Consumer x = new Consumer() { - @Override - public void accept(Triple item) { - Node p = item.getPredicate() ; - Node o = item.getObject() ; - - if ( p.equals(RDF.type.asNode()) ) - return ; - // JENA-1744 : split as a "Curie" (at the last / or #, regardless of th characters in a lcoal name). - // Curie : https://www.w3.org/TR/curie/ - String x = SplitIRI.localname(p.getURI()); - - if ( ctx.containsKey(x) ) { - } else if ( o.isBlank() || o.isURI() ) { - // add property as a property (the object is an IRI) + Consumer x = (Triple item) -> { + Node p = item.getPredicate() ; + Node o = item.getObject() ; + + if ( p.equals(RDF.type.asNode()) ) + return ; + // JENA-1744 : split as a "Curie" (at the last / or #, regardless of the characters in a local name). + // Curie : https://www.w3.org/TR/curie/ + String uriStr = SplitIRI.localname(p.getURI()); + + if ( ctx.containsKey(uriStr) ) { + } else if ( o.isBlank() || o.isURI() ) { + // add property as a property (the object is an IRI) + Map x2 = new LinkedHashMap<>() ; + x2.put("@id", p.getURI()) ; + x2.put("@type", "@id") ; + ctx.put(uriStr, x2) ; + } else if ( o.isLiteral() ) { + String literalDatatypeURI = o.getLiteralDatatypeURI() ; + if ( literalDatatypeURI != null ) { + // add property as a typed attribute (the object is a + // typed literal) Map x2 = new LinkedHashMap<>() ; x2.put("@id", p.getURI()) ; - x2.put("@type", "@id") ; - ctx.put(x, x2) ; - } else if ( o.isLiteral() ) { - String literalDatatypeURI = o.getLiteralDatatypeURI() ; - if ( literalDatatypeURI != null ) { - // add property as a typed attribute (the object is a - // typed literal) - Map x2 = new LinkedHashMap<>() ; - x2.put("@id", p.getURI()) ; - if (! isLangString(o) && ! isSimpleString(o) ) - // RDF 1.1 : Skip if rdf:langString or xsd:string. - x2.put("@type", literalDatatypeURI) ; - ctx.put(x, x2) ; - } else { - // add property as an untyped attribute (the object is - // an untyped literal) - ctx.put(x, p.getURI()) ; - } + if (! isLangString(o) && ! isSimpleString(o) ) + // RDF 1.1 : Skip if rdf:langString or xsd:string. + x2.put("@type", literalDatatypeURI) ; + ctx.put(uriStr, x2) ; + } else { + // add property as an untyped attribute (the object is + // an untyped literal) + ctx.put(uriStr, p.getURI()) ; } } } ; - g.find(ANY).forEachRemaining(x); + g.find(ANY).forEach(x); } /** diff --git a/jena-arq/src/main/java/org/apache/jena/riot/writer/TurtleShell.java b/jena-arq/src/main/java/org/apache/jena/riot/writer/TurtleShell.java index 8da150129c7..0a6f8139cfe 100644 --- a/jena-arq/src/main/java/org/apache/jena/riot/writer/TurtleShell.java +++ b/jena-arq/src/main/java/org/apache/jena/riot/writer/TurtleShell.java @@ -34,7 +34,7 @@ import org.apache.jena.graph.Node_Triple; import org.apache.jena.graph.Triple; import org.apache.jena.riot.RIOT; -import org.apache.jena.riot.other.GLib; +import org.apache.jena.riot.other.G; import org.apache.jena.riot.out.NodeFormatter; import org.apache.jena.riot.out.NodeFormatterTTL; import org.apache.jena.riot.out.NodeFormatterTTL_MultiLine; @@ -326,7 +326,7 @@ private Collection triplesOfSubject(Node subj) { } private Iterator listSubjects() { - return GLib.listSubjects(graph) ; + return G.listSubjects(graph) ; } // ---- Data access diff --git a/jena-arq/src/main/java/org/apache/jena/riot/writer/WriterStreamRDFBlocks.java b/jena-arq/src/main/java/org/apache/jena/riot/writer/WriterStreamRDFBlocks.java index 8eaaf643636..9cd740fe247 100644 --- a/jena-arq/src/main/java/org/apache/jena/riot/writer/WriterStreamRDFBlocks.java +++ b/jena-arq/src/main/java/org/apache/jena/riot/writer/WriterStreamRDFBlocks.java @@ -27,7 +27,7 @@ import org.apache.jena.atlas.io.IndentedWriter ; import org.apache.jena.graph.Node ; import org.apache.jena.graph.Triple ; -import org.apache.jena.riot.other.GLib ; +import org.apache.jena.riot.other.G; import org.apache.jena.riot.system.RiotLib ; import org.apache.jena.sparql.core.Quad ; import org.apache.jena.sparql.util.Context; @@ -93,7 +93,7 @@ protected void printBatchQuads(Node g, Node s, List quads) { startGraph(g) ; lastGraph = g ; } - List triples = GLib.quads2triples(quads.iterator()).toList() ; + List triples = G.quads2triples(quads.iterator()).toList() ; printBatch(s, triples) ; // No trailing "." has been printed. lastSubject = s ; diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphCollection.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphCollection.java index aed8156cfa7..973013dc76f 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphCollection.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphCollection.java @@ -18,8 +18,6 @@ package org.apache.jena.sparql.core; -import static org.apache.jena.sparql.util.graph.GraphUtils.triples2quadsDftGraph ; - import java.util.Iterator ; import java.util.List ; import java.util.Objects ; @@ -28,8 +26,8 @@ import org.apache.jena.atlas.iterator.IteratorConcat ; import org.apache.jena.graph.Graph ; import org.apache.jena.graph.Node ; +import org.apache.jena.riot.other.G; import org.apache.jena.shared.JenaException ; -import static org.apache.jena.sparql.util.graph.GraphUtils.* ; /** Base class for implementations of a DatasetGraph as a set of graphs. * This can be a fixed collection or a changeable collection depending @@ -58,7 +56,7 @@ public void delete(Quad quad) @Override protected Iterator findInDftGraph(Node s, Node p , Node o) { - return triples2quadsDftGraph(getDefaultGraph().find(s, p, o)) ; + return G.triples2quadsDftGraph(getDefaultGraph().find(s, p, o)) ; } @Override @@ -67,7 +65,7 @@ protected Iter findInSpecificNamedGraph(Node g, Node s, Node p , Node o) Graph graph = fetchGraph(g) ; if ( graph == null ) return Iter.nullIter() ; - return triples2quads(g, graph.find(s, p, o)) ; + return G.triples2quads(g, graph.find(s, p, o)) ; } @Override diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMap.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMap.java index 693f6fe3c43..399100470b4 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMap.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMap.java @@ -18,9 +18,6 @@ package org.apache.jena.sparql.core; -import static org.apache.jena.sparql.util.graph.GraphUtils.triples2quads ; -import static org.apache.jena.sparql.util.graph.GraphUtils.triples2quadsDftGraph ; - import java.util.HashMap ; import java.util.Iterator ; import java.util.Map ; @@ -32,6 +29,7 @@ import org.apache.jena.graph.Triple ; import org.apache.jena.query.ReadWrite ; import org.apache.jena.query.TxnType; +import org.apache.jena.riot.other.G; import org.apache.jena.sparql.ARQException ; import org.apache.jena.sparql.core.DatasetGraphFactory.GraphMaker ; import org.apache.jena.sparql.graph.GraphUnionRead ; @@ -126,13 +124,13 @@ protected void deleteFromNamedGraph(Node g, Node s, Node p, Node o) { @Override protected Iterator findInDftGraph(Node s, Node p, Node o) { Iterator iter = getDefaultGraph().find(s, p, o) ; - return triples2quadsDftGraph(iter) ; + return G.triples2quadsDftGraph(iter) ; } @Override protected Iterator findInSpecificNamedGraph(Node g, Node s, Node p, Node o) { Iterator iter = getGraph(g).find(s, p, o) ; - return triples2quads(g, iter) ; + return G.triples2quads(g, iter) ; } @Override diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphOne.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphOne.java index 1323c0afbdb..b7acb8f1ac3 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphOne.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphOne.java @@ -18,8 +18,6 @@ package org.apache.jena.sparql.core; -import static org.apache.jena.sparql.util.graph.GraphUtils.triples2quadsDftGraph; - import java.util.Iterator; import org.apache.jena.atlas.iterator.Iter; @@ -30,6 +28,7 @@ import org.apache.jena.query.ReadWrite; import org.apache.jena.query.TxnType; import org.apache.jena.reasoner.InfGraph; +import org.apache.jena.riot.other.G; import org.apache.jena.sparql.graph.GraphOps; import org.apache.jena.sparql.graph.GraphZero; @@ -189,7 +188,7 @@ public void removeGraph(Node graphName) { // -- Not needed -- implement find(g,s,p,o) directly. @Override protected Iterator findInDftGraph(Node s, Node p, Node o) { - return triples2quadsDftGraph(graph.find(s, p, o)); + return G.triples2quadsDftGraph(graph.find(s, p, o)); } @Override @@ -216,7 +215,7 @@ protected static boolean isDefaultGraph(Node quadGraphNode) { @Override public Iterator find(Node g, Node s, Node p, Node o) { if ( isWildcard(g) || isDefaultGraph(g) ) - return triples2quadsDftGraph(graph.find(s, p, o)); + return G.triples2quadsDftGraph(graph.find(s, p, o)); else return new NullIterator<>(); } diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/GraphView.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/GraphView.java index 6ff367c7c40..f59e7b3d424 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/GraphView.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/GraphView.java @@ -22,9 +22,12 @@ import org.apache.jena.atlas.iterator.Iter ; import org.apache.jena.atlas.lib.Sync ; -import org.apache.jena.graph.*; +import org.apache.jena.graph.Capabilities; +import org.apache.jena.graph.Node; +import org.apache.jena.graph.TransactionHandler; +import org.apache.jena.graph.Triple; import org.apache.jena.graph.impl.GraphBase ; -import org.apache.jena.riot.other.GLib ; +import org.apache.jena.riot.other.G; import org.apache.jena.shared.AddDeniedException; import org.apache.jena.shared.DeleteDeniedException; import org.apache.jena.shared.JenaException ; @@ -118,7 +121,7 @@ protected ExtendedIterator graphBaseFind(Node s, Node p, Node o) { if ( Quad.isUnionGraph(gn) ) return graphUnionFind(s, p, o) ; Node g = graphNode(gn) ; - Iterator iter = GLib.quads2triples(dsg.find(g, s, p, o)) ; + Iterator iter = G.quads2triples(dsg.find(g, s, p, o)) ; return WrappedIterator.createNoRemove(iter) ; } @@ -132,7 +135,7 @@ protected ExtendedIterator graphUnionFind(Node s, Node p, Node o) { // For example, Iter.distinctAdjacent is a lot cheaper than Iter.distinct // but assumes things come back in a particular order Iterator iterQuads = getDataset().find(g, s, p, o) ; - Iterator iter = GLib.quads2triples(iterQuads) ; + Iterator iter = G.quads2triples(iterQuads) ; // Suppress duplicates after projecting to triples. iter = Iter.distinct(iter) ; return WrappedIterator.createNoRemove(iter) ; diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/mem/DatasetGraphInMemory.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/mem/DatasetGraphInMemory.java index 85099f493b1..ffacc0af262 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/mem/DatasetGraphInMemory.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/mem/DatasetGraphInMemory.java @@ -22,7 +22,6 @@ import static org.apache.jena.graph.Node.ANY; import static org.apache.jena.query.ReadWrite.WRITE; import static org.apache.jena.sparql.core.Quad.isUnionGraph; -import static org.apache.jena.sparql.util.graph.GraphUtils.triples2quadsDftGraph ; import static org.apache.jena.system.Txn.calculateRead; import static org.apache.jena.system.Txn.executeWrite; import static org.slf4j.LoggerFactory.getLogger; @@ -34,9 +33,12 @@ import java.util.function.Supplier; import org.apache.jena.atlas.lib.InternalErrorException ; -import org.apache.jena.graph.*; +import org.apache.jena.graph.Graph; +import org.apache.jena.graph.Node; +import org.apache.jena.graph.Triple; import org.apache.jena.query.ReadWrite; import org.apache.jena.query.TxnType; +import org.apache.jena.riot.other.G; import org.apache.jena.shared.Lock; import org.apache.jena.shared.LockMRPlusSW; import org.apache.jena.sparql.JenaTransactionException; @@ -322,7 +324,7 @@ private Iterator quadsFinder(final Node g, final Node s, final Node p, fin } private Iterator triplesFinder(final Node s, final Node p, final Node o) { - return triples2quadsDftGraph(defaultGraph().find(s, p, o).iterator()); + return G.triples2quadsDftGraph(defaultGraph().find(s, p, o).iterator()); } @Override diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/engine/binding/BindingBase.java b/jena-arq/src/main/java/org/apache/jena/sparql/engine/binding/BindingBase.java index 59c2a93bd30..06cf69033d3 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/binding/BindingBase.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/binding/BindingBase.java @@ -28,7 +28,7 @@ import org.apache.jena.sparql.util.FmtUtils ; -/** Machinary encapsulating a mapping from a name to a value. +/** Machinery encapsulating a mapping from a name to a value. * The "parent" is a shared, immutable, common set of bindings. * An association of var/node must not override a setting in the parent. * diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterTriplePattern.java b/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterTriplePattern.java index b82753dd124..58b244a16dc 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterTriplePattern.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIterTriplePattern.java @@ -171,7 +171,7 @@ protected void closeIterator() @Override protected void requestCancel() { - // The QueryIteratorBase machinary will do the real work. + // The QueryIteratorBase machinery will do the real work. cancelled = true ; } } diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIteratorBase.java b/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIteratorBase.java index 29f5f68fdbd..d56c95de23b 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIteratorBase.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/iterator/QueryIteratorBase.java @@ -30,7 +30,7 @@ import org.apache.jena.sparql.util.PrintSerializableBase ; /** - * This class provides the general machinary for iterators. This includes: + * This class provides the general machinery for iterators. This includes: *
    *
  • autoclose when the iterator runs out
  • *
  • ensuring query iterators only contain Bindings
  • diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/engine/optimizer/reorder/ReorderTransformationSubstitution.java b/jena-arq/src/main/java/org/apache/jena/sparql/engine/optimizer/reorder/ReorderTransformationSubstitution.java index d05f361dfc9..6cdbaff32b2 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/optimizer/reorder/ReorderTransformationSubstitution.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/optimizer/reorder/ReorderTransformationSubstitution.java @@ -35,7 +35,7 @@ import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; -/** Machinary. +/** Machinery. * This code implements the connectiveness assumed by execution based on substitution (index joins). * i.e. if { ?x :p ?v . ?x :q ?w } then ?x is TERM * at the second triple. diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprNode.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprNode.java index 7dd7b3e8998..28af6fbfc66 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprNode.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/ExprNode.java @@ -31,7 +31,7 @@ /** A node that is a constraint expression that can be evaluated * An Expr is already a Constraint - ExprNode is the base implementation - * of all Expr classes that provides the Constraint machinary. */ + * of all Expr classes that provides the Constraint machinery. */ public abstract class ExprNode implements Expr { diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/aggregate/AccumulatorExpr.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/aggregate/AccumulatorExpr.java index eda0fa30796..d8c5de3f35a 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/aggregate/AccumulatorExpr.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/aggregate/AccumulatorExpr.java @@ -39,7 +39,7 @@ public abstract class AccumulatorExpr implements Accumulator protected AccumulatorExpr(Expr expr, boolean makeDistinct) { this.expr = expr; - // Not all subclasses use the machinary here to handled DISTINCT. + // Not all subclasses use the machinery here to handled DISTINCT. // SAMPLE(DISTINCT) and COUNT(DISTINCT *) are different. this.makeDistinct = makeDistinct ; this.values = makeDistinct ? new HashSet<>() : null ; diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueLang.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueLang.java index 88c329d642e..72ea820df62 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueLang.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueLang.java @@ -29,7 +29,7 @@ * A string + language tag which is not "" */ public class NodeValueLang extends NodeValue { - // We could extends NodeValueString for the machinary + // We could extends NodeValueString for the machinery // but it get confusing as then it is a NodeValueString // but isString is false. diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/graph/GraphOps.java b/jena-arq/src/main/java/org/apache/jena/sparql/graph/GraphOps.java index 63bedc9d525..cc56ac0e2a2 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/graph/GraphOps.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/graph/GraphOps.java @@ -91,7 +91,7 @@ public static void deleteAll(Graph g, Iterable iter) { deleteAll(g, iter.iterator()) ; } - /** Remove all layers of graph wrapping. Returns the orinalk graph is not wrapped at all.*/ + /** Remove all layers of graph wrapping. Returns the original graph is not wrapped at all.*/ public static Graph unwrapAll(Graph graph) { Graph graph1 = graph; for (;;) { diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/graph/NodeConst.java b/jena-arq/src/main/java/org/apache/jena/sparql/graph/NodeConst.java index 522392679b0..b86c9a16bf9 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/graph/NodeConst.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/graph/NodeConst.java @@ -22,8 +22,11 @@ import org.apache.jena.datatypes.xsd.XSDDatatype; import org.apache.jena.graph.Node; import org.apache.jena.graph.NodeFactory; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.ResourceFactory; import org.apache.jena.vocabulary.OWL; import org.apache.jena.vocabulary.RDF; +import org.apache.jena.vocabulary.RDFS; /** Some node constants */ public class NodeConst { @@ -43,6 +46,8 @@ private static Node uri(String uriStr) { public static final Node nodeTen = literal("10", XSDDatatype.XSDinteger); public static final Node nodeMinusOne = literal("-1", XSDDatatype.XSDinteger); public static final Node emptyString = NodeFactory.createLiteral(""); + public static final Node TRUE = NodeConst.nodeTrue; + public static final Node FALSE = NodeConst.nodeFalse; // It should be safe to use RDF.Nodes. // Fallback code "just in case" @@ -58,4 +63,16 @@ private static Node uri(String uriStr) { public static final Node nodeOwlSameAs = OWL.sameAs.asNode(); // uri("http://www.w3.org/2002/07/owl#sameAs") public static final Node rdfLangString = RDF.Nodes.langString; public static final RDFDatatype dtLangString = RDF.dtLangString; + + public static Literal mTRUE = ResourceFactory.createTypedLiteral(true); + public static Literal mFALSE = ResourceFactory.createTypedLiteral(false); + +// public static Node rdfType = RDF.Nodes.type; + public static Node rdfsClass = RDFS.Nodes.Class; + public static Node rdfsSubclassOf = RDFS.subClassOf.asNode(); + + public static final Node FIRST = RDF.first.asNode() ; + public static final Node REST = RDF.rest.asNode() ; + public static final Node NIL = RDF.nil.asNode() ; + } diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/DyadicDatasetGraph.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/DyadicDatasetGraph.java index 66e2e3066ac..063457cf56f 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/util/DyadicDatasetGraph.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/DyadicDatasetGraph.java @@ -25,7 +25,6 @@ import static org.apache.jena.graph.Node.ANY; import static org.apache.jena.query.TxnType.READ; import static org.apache.jena.sparql.core.Quad.defaultGraphIRI; -import static org.apache.jena.sparql.util.graph.GraphUtils.triples2quads; import java.util.Iterator; import java.util.Objects; @@ -36,6 +35,7 @@ import org.apache.jena.graph.compose.MultiUnion; import org.apache.jena.query.ReadWrite; import org.apache.jena.query.TxnType; +import org.apache.jena.riot.other.G; import org.apache.jena.shared.Lock; import org.apache.jena.sparql.JenaTransactionException; import org.apache.jena.sparql.core.DatasetGraph; @@ -195,7 +195,7 @@ public Iterator findNG(Node g, Node s, Node p, Node o) { } protected Iterator findInOneGraph(Node g, Node s, Node p, Node o) { - return triples2quads(g, getGraph(g).find(s, p, o)); + return G.triples2quads(g, getGraph(g).find(s, p, o)); } @Override diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/GNode.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/GNode.java index 983f0cd4d46..de5b852951c 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/GNode.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/graph/GNode.java @@ -26,8 +26,30 @@ import org.apache.jena.sparql.core.BasicPattern ; +/** + * A {@code GNode} pair of (graph, node in graph) with an abstracted "findable" + * operation so it work for graphs and collections of triples. + *

    + * See {@link GraphList}. + */ public class GNode { + public static GNode create(Graph graph, Node node) { + return new GNode(graph, node); + } + + public static GNode subject(Graph graph, Triple triple) { + return triple == null ? null : create(graph, triple.getSubject()); + } + + public static GNode predicate(Graph graph, Triple triple) { + return triple == null ? null : create(graph, triple.getPredicate()); + } + + public static GNode object(Graph graph, Triple triple) { + return triple == null ? null : create(graph, triple.getObject()); + } + public final Findable findable ; public final Node node ; 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 907a43446aa..98e456bea57 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 @@ -27,6 +27,7 @@ import org.apache.jena.graph.Triple ; import org.apache.jena.query.* ; import org.apache.jena.rdf.model.* ; +import org.apache.jena.riot.other.G; import org.apache.jena.sparql.core.Quad ; import org.apache.jena.sparql.util.NotUniqueException ; import org.apache.jena.sparql.util.PropertyRequiredException ; @@ -42,14 +43,16 @@ public class GraphUtils { * Convert an iterator of triples into quads for the default graph. This is * {@link Quad#defaultGraphIRI}, not {@link Quad#defaultGraphNodeGenerated}, which is * for quads outside a dataset, usually the output of parsers. + * @deprecated Use {@link G#triples2quadsDftGraph(Iterator)} instead */ - public static Iterator triples2quadsDftGraph(Iterator iter) { - return triples2quads(Quad.defaultGraphIRI, iter) ; + public static Iter triples2quadsDftGraph(Iterator iter) { + return G.triples2quadsDftGraph(iter); } - /** Convert an iterator of triples into quads for the specified graph name. */ + /** Convert an iterator of triples into quads for the specified graph name. + * @deprecated Use {@link G#triples2quads(Node,Iterator)} instead*/ public static Iter triples2quads(final Node graphNode, Iterator iter) { - return Iter.iter(iter).map(t -> new Quad(graphNode, t)) ; + return G.triples2quads(graphNode, iter); } public static List multiValueString(Resource r, Property p) { diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestXSDFuncOp.java b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestXSDFuncOp.java index 552495016f6..9c4ca85ee41 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestXSDFuncOp.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestXSDFuncOp.java @@ -777,7 +777,7 @@ private static NodeValue parse(String str) { Node n = SSE.parseNode(str) ; return NodeValue.makeNode(n) ; } - // abs is a test of Function.unaryOp machinary + // abs is a test of Function.unaryOp machinery @Test public void testAbs1() { NodeValue nv = NodeValue.makeInteger(2) ; diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/util/TestList.java b/jena-arq/src/test/java/org/apache/jena/sparql/util/TestList.java index adbfead5f7c..3e6cd251343 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/util/TestList.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/util/TestList.java @@ -36,7 +36,7 @@ import org.apache.jena.rdf.model.ModelFactory ; import org.apache.jena.riot.Lang ; import org.apache.jena.riot.RDFDataMgr ; -import org.apache.jena.riot.other.GLib ; +import org.apache.jena.riot.other.G; import org.apache.jena.sparql.sse.SSE ; import org.apache.jena.sparql.util.graph.GNode ; import org.apache.jena.sparql.util.graph.GraphList ; @@ -239,7 +239,7 @@ private static GNode parse(String str) private static void testGraphListMember(Node s, Node...expected) { Node list = listOf(graph, s) ; Iterator iter = GraphList.listMember(graph, list, Node.ANY) ; - Iterator x = GLib.triple2object(iter) ; + Iterator x = G.triple2object(iter) ; List z = Iter.toList(x) ; check(z, expected) ; } diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamReader.java b/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamReader.java index c441e593325..bec5090d46e 100644 --- a/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamReader.java +++ b/jena-base/src/main/java/org/apache/jena/atlas/io/CharStreamReader.java @@ -21,7 +21,7 @@ import java.io.IOException ; import java.io.Reader ; -/** Machinary to add Reader functionality to a CharStream */ +/** Machinery to add Reader functionality to a CharStream */ public abstract class CharStreamReader extends Reader implements CharStream { @Override diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/Iter.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Iter.java index 97661fa92ea..3dc622b20af 100644 --- a/jena-base/src/main/java/org/apache/jena/atlas/iterator/Iter.java +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Iter.java @@ -68,7 +68,7 @@ public static Stream asStream(Iterator iterator) { public static Stream asStream(Iterator iterator, boolean parallel) { // Why isn't there a JDK operation for Iterator -> (sequential) stream? - int characteristics = 0 ; //Spliterator.IMMUTABLE; + int characteristics = Spliterator.IMMUTABLE; return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, characteristics), parallel); } diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/tuple/Tuple.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/tuple/Tuple.java index a95c753baf4..e586c19eba8 100644 --- a/jena-base/src/main/java/org/apache/jena/atlas/lib/tuple/Tuple.java +++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/tuple/Tuple.java @@ -70,7 +70,7 @@ public default void copyInto(X[] array) { copyInto(array, 0, len()); } - /** Copy the elements of this Tuple into the array */ + /** Copy the elements of this Tuple start at 'start' into the array */ public default void copyInto(X[] array, int start) { copyInto(array, start, len()); } diff --git a/jena-core/src/main/java/org/apache/jena/datatypes/xsd/impl/XSDPlainType.java b/jena-core/src/main/java/org/apache/jena/datatypes/xsd/impl/XSDPlainType.java index 2e181bb8ab1..07687523c5c 100644 --- a/jena-core/src/main/java/org/apache/jena/datatypes/xsd/impl/XSDPlainType.java +++ b/jena-core/src/main/java/org/apache/jena/datatypes/xsd/impl/XSDPlainType.java @@ -21,7 +21,7 @@ import org.apache.jena.datatypes.xsd.XSDDatatype ; import org.apache.jena.graph.impl.LiteralLabel ; -/** A datatype that does not use the Xerces machinary for isEqual, yet is still an XSDDatatype. +/** A datatype that does not use the Xerces machinery for isEqual, yet is still an XSDDatatype. * Assumes no derived XSD datatypes. */ diff --git a/jena-core/src/main/java/org/apache/jena/graph/GraphUtil.java b/jena-core/src/main/java/org/apache/jena/graph/GraphUtil.java index 1b185e7c22d..14c25418c31 100644 --- a/jena-core/src/main/java/org/apache/jena/graph/GraphUtil.java +++ b/jena-core/src/main/java/org/apache/jena/graph/GraphUtil.java @@ -293,7 +293,7 @@ private static void deleteIteratorWorkerDirect(Graph graph, Iterator it) * @implNote * This is designed for the case of {@code dstGraph} being comparable or much larger than * {@code srcGraph} or {@code srcGraph} having a lot of triples to actually be - * deleted from {@code dstGraph}. This includes teh case of large, persistent {@code dstGraph}. + * deleted from {@code dstGraph}. This includes the case of large, persistent {@code dstGraph}. *

    * It is not designed for a large {@code srcGraph} and large {@code dstGraph} * with only a few triples in common to delete from {@code dstGraph}. It is better to diff --git a/jena-core/src/main/java/org/apache/jena/util/SplitIRI.java b/jena-core/src/main/java/org/apache/jena/util/SplitIRI.java index 1190647dbd1..b3188232ba3 100644 --- a/jena-core/src/main/java/org/apache/jena/util/SplitIRI.java +++ b/jena-core/src/main/java/org/apache/jena/util/SplitIRI.java @@ -33,7 +33,7 @@ * or last {@code #}, if present. * See {@link #splitpoint} for more details. *

    - * This code form the machinary behind {@link Node#getLocalName} + * This code form the machinery behind {@link Node#getLocalName} * {@link Node#getNameSpace} for URI Nodes. *

    * {@link #localnameTTL} is strict Turtle; it is the same local name as diff --git a/jena-core/src/main/java/org/apache/jena/util/iterator/ExtendedIterator.java b/jena-core/src/main/java/org/apache/jena/util/iterator/ExtendedIterator.java index 831f7698860..d47b92d7200 100644 --- a/jena-core/src/main/java/org/apache/jena/util/iterator/ExtendedIterator.java +++ b/jena-core/src/main/java/org/apache/jena/util/iterator/ExtendedIterator.java @@ -19,6 +19,7 @@ package org.apache.jena.util.iterator; import java.util.*; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; @@ -71,7 +72,18 @@ public interface ExtendedIterator extends ClosableIterator */ public ExtendedIterator mapWith( Function map1 ); - /** + /** + * Execute an action on each element of the iterator. + * This operation ends and closes the {@code ExtendedIterator} even if there is an exception. + * Shorter name for "{@code Iterator.forEachRemaining}", adding exception handling. + */ + public default void forEach( Consumer action) { + try { + forEachRemaining(action); + } finally { close() ; } + } + + /** Answer a list of the [remaining] elements of this iterator, in order, consuming this iterator. */ diff --git a/jena-core/src/test/java/org/apache/jena/graph/test/AbstractTestGraph.java b/jena-core/src/test/java/org/apache/jena/graph/test/AbstractTestGraph.java index c263303e233..af6307e1e9b 100644 --- a/jena-core/src/test/java/org/apache/jena/graph/test/AbstractTestGraph.java +++ b/jena-core/src/test/java/org/apache/jena/graph/test/AbstractTestGraph.java @@ -975,7 +975,6 @@ protected Graph remove( Graph toUpdate, Graph toRemove ) return toUpdate; } - protected Graph copy( Graph g ) { Graph result = Factory.createDefaultGraph(); diff --git a/jena-db/jena-dboe-trans-data/src/test/java/org/apache/jena/dboe/trans/bplustree/TS_TxnBPTree.java b/jena-db/jena-dboe-trans-data/src/test/java/org/apache/jena/dboe/trans/bplustree/TS_TxnBPTree.java index d3581a99974..69226803ff6 100644 --- a/jena-db/jena-dboe-trans-data/src/test/java/org/apache/jena/dboe/trans/bplustree/TS_TxnBPTree.java +++ b/jena-db/jena-dboe-trans-data/src/test/java/org/apache/jena/dboe/trans/bplustree/TS_TxnBPTree.java @@ -25,7 +25,7 @@ @RunWith(Suite.class) @Suite.SuiteClasses( { - // Non-transactional tests -- that is, algorithms and machinary. + // Non-transactional tests -- that is, algorithms and machinery. TestBPTreeRecordsNonTxn.class, TestBPlusTreeIndexNonTxn.class, TestBPlusTreeNonTxn.class, diff --git a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/GraphTDB.java b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/GraphTDB.java index 940b7b3ccc5..f200ca7abde 100644 --- a/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/GraphTDB.java +++ b/jena-db/jena-tdb2/src/main/java/org/apache/jena/tdb2/store/GraphTDB.java @@ -29,7 +29,7 @@ import org.apache.jena.dboe.storage.system.GraphViewStorage; import org.apache.jena.graph.Node; import org.apache.jena.graph.Triple; -import org.apache.jena.riot.other.GLib; +import org.apache.jena.riot.other.G; import org.apache.jena.sparql.core.Quad; import org.apache.jena.tdb2.TDBException; import org.apache.jena.tdb2.store.nodetupletable.NodeTupleTable; @@ -106,7 +106,7 @@ private static Iterator projectQuadsToTriples(Node graphNode, Iterator graphUnionFind(Node s, Node p, Node o) { Node g = Quad.unionGraph; Iterator iterQuads = getDSG().find(g, s, p, o); - Iterator iter = GLib.quads2triples(iterQuads); + Iterator iter = G.quads2triples(iterQuads); // Suppress duplicates after projecting to triples. // TDB guarantees that duplicates are adjacent. // See SolverLib. diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/Shapes.java b/jena-shacl/src/main/java/org/apache/jena/shacl/Shapes.java index 9ed12706490..12401a094af 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/Shapes.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/Shapes.java @@ -29,9 +29,9 @@ import org.apache.jena.graph.Node; import org.apache.jena.rdf.model.Model; import org.apache.jena.riot.RDFDataMgr; +import org.apache.jena.riot.other.G; +import org.apache.jena.riot.other.RDFDataException; import org.apache.jena.shacl.engine.Targets; -import org.apache.jena.shacl.lib.G; -import org.apache.jena.shacl.lib.RDFDataException; import org.apache.jena.shacl.parser.Shape; import org.apache.jena.shacl.parser.ShapesParser; import org.apache.jena.sys.JenaSystem; diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/ValidationReport.java b/jena-shacl/src/main/java/org/apache/jena/shacl/ValidationReport.java index 586161a8f05..1a743d5df59 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/ValidationReport.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/ValidationReport.java @@ -27,8 +27,8 @@ 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.riot.other.G; import org.apache.jena.shacl.engine.ShaclPaths; -import org.apache.jena.shacl.lib.G; import org.apache.jena.shacl.parser.Constraint; import org.apache.jena.shacl.parser.Shape; import org.apache.jena.shacl.sys.C; diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/ShapeOutputVisitor.java b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/ShapeOutputVisitor.java index 818e646b536..de0af336eba 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/ShapeOutputVisitor.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/compact/writer/ShapeOutputVisitor.java @@ -75,9 +75,10 @@ public void visit(PropertyShape propertyShape) { boolean minMaxCountDone = false; for ( Constraint c : propertyShape.getConstraints()) { + // Min/Max is a special case. if ( SHACL.MinCountConstraintComponent.equals(c.getComponent()) || SHACL.MaxCountConstraintComponent.equals(c.getComponent()) ) { - // Print on encounter. preserves the look of the input. + // Print on encounter. Preserves the look of the input. if ( ! minMaxCountDone ) { // Special! if ( minCount != -1 || maxCount!= -1 ) { @@ -87,9 +88,10 @@ public void visit(PropertyShape propertyShape) { } } minMaxCountDone = true; + } else { + out.print(" "); + propertyConstraint(c); } - out.print(" "); - propertyConstraint(c); } out.println(" ."); diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ShaclPaths.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ShaclPaths.java index dcc07b2de89..efdef05c58b 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ShaclPaths.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ShaclPaths.java @@ -30,9 +30,9 @@ import org.apache.jena.graph.Node; import org.apache.jena.graph.NodeFactory; import org.apache.jena.graph.Triple; +import org.apache.jena.riot.other.G; import org.apache.jena.riot.out.NodeFormatter; import org.apache.jena.riot.system.StreamRDF; -import org.apache.jena.shacl.lib.G; import org.apache.jena.shacl.lib.ShLib; import org.apache.jena.shacl.parser.ShaclParseException; import org.apache.jena.shacl.sys.C; diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/SparqlConstraints.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/SparqlConstraints.java index 0e38bee115a..a803675f6e7 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/SparqlConstraints.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/SparqlConstraints.java @@ -20,13 +20,15 @@ import java.util.StringJoiner; +import org.apache.jena.atlas.iterator.Iter; import org.apache.jena.atlas.lib.StrUtils; import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; +import org.apache.jena.graph.Triple; import org.apache.jena.query.*; import org.apache.jena.rdf.model.impl.Util; +import org.apache.jena.riot.other.G; import org.apache.jena.shacl.engine.constraint.SparqlConstraint; -import org.apache.jena.shacl.lib.G; import org.apache.jena.shacl.lib.ShLib; import org.apache.jena.shacl.parser.Constraint; import org.apache.jena.shacl.parser.ShaclParseException; @@ -35,6 +37,7 @@ import org.apache.jena.sparql.core.Var; import org.apache.jena.sparql.engine.binding.Binding; import org.apache.jena.sparql.graph.NodeConst; +import org.apache.jena.util.iterator.ExtendedIterator; public class SparqlConstraints { // 5. SPARQL-based Constraints @@ -72,7 +75,7 @@ public static Constraint parseSparqlConstraint(Graph shapesGraph, Node shape, No */ //G.contains(shapesGraph, sparqlConstraintNode, C.rdfType, SHACL.SPARQLConstraint); Node message = G.getZeroOrOneSP(shapesGraph, sparqlConstraintNode, SHACL.message); - boolean deactivated = G.absentOrOne(shapesGraph, sparqlConstraintNode, SHACL.deactivated, NodeConst.nodeTrue); + boolean deactivated = absentOrOne(shapesGraph, sparqlConstraintNode, SHACL.deactivated, NodeConst.nodeTrue); // XXX Optimize prefixes acquisition in case of use from more than one place. String prefixes = prefixes(shapesGraph, sparqlConstraintNode); @@ -91,6 +94,27 @@ public static Constraint parseSparqlConstraint(Graph shapesGraph, Node shape, No throw new ShaclParseException("SPARQL parse error: "+ex.getMessage()+"\n"+qs); } } + + /** + * Test for zero or one occurrences of a tripel pattern that is expected to be + * Returns false for zero, true for one. + * Throws an exception on two or more. + */ + private static boolean absentOrOne(Graph g, Node s, Node p, Node o) { + ExtendedIterator iter = G.find(g, s, p, null); + try { + if ( ! iter.hasNext() ) + return false; + iter.next(); + if ( ! iter.hasNext() ) + return true; + long x = Iter.count(G.find(g, s, p, null)); + throw new ShaclParseException("More than one (" + x + ") of " + String.format("(%s %s %s)", s, p, o)); + } + finally { iter.close(); } + } + + public static String prefixes(Graph shapesGraph, Node sparqlNode) { // XXX Ignores sparqlNode ATM diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/TargetOps.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/TargetOps.java index 155eb14239a..d02f2abc7d9 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/TargetOps.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/TargetOps.java @@ -19,14 +19,13 @@ package org.apache.jena.shacl.engine; -import static org.apache.jena.shacl.lib.G.allNodesOfType; - import java.util.*; import org.apache.jena.atlas.lib.CollectionUtils; import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; import org.apache.jena.graph.Triple; +import org.apache.jena.riot.other.G; import org.apache.jena.riot.out.NodeFormatter; import org.apache.jena.shacl.lib.ShLib; import org.apache.jena.shacl.sys.C; @@ -85,11 +84,11 @@ public static Set shapesTargetSubjectsOf(Graph shapesGraph) { /** Implicit class targets : section 2.1.3.3 Implicit Class Targets */ public static Set implicitClassTargets(Graph shapesGraph) { - Set allClasses = allNodesOfType(shapesGraph, C.rdfsClass); + Set allClasses = G.allNodesOfTypeRDFS(shapesGraph, C.rdfsClass); if ( allClasses.isEmpty() ) return Collections.emptySet(); - Set nodeShapes = allNodesOfType(shapesGraph, SHACL.NodeShape); - Set propertyShapes = allNodesOfType(shapesGraph, SHACL.PropertyShape); + Set nodeShapes = G.allNodesOfTypeRDFS(shapesGraph, SHACL.NodeShape); + Set propertyShapes = G.allNodesOfTypeRDFS(shapesGraph, SHACL.PropertyShape); // A = A intersection B nodeShapes.retainAll(allClasses); propertyShapes.retainAll(allClasses); diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/Targets.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/Targets.java index de563f0cc7a..9a464028ad1 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/Targets.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/Targets.java @@ -26,7 +26,7 @@ import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; -import org.apache.jena.shacl.lib.G; +import org.apache.jena.riot.other.G; import org.apache.jena.shacl.lib.ShLib; import org.apache.jena.shacl.vocabulary.SHACL; diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClassConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClassConstraint.java index 1d347545da3..f284441ccc6 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClassConstraint.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClassConstraint.java @@ -21,15 +21,15 @@ import static org.apache.jena.shacl.compact.writer.CompactOut.compact; import static org.apache.jena.shacl.lib.ShLib.displayStr; -import java.util.List; +import java.util.Collection; import java.util.Objects; import org.apache.jena.atlas.io.IndentedWriter; import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; +import org.apache.jena.riot.other.G; import org.apache.jena.riot.out.NodeFormatter; import org.apache.jena.shacl.engine.ValidationContext; -import org.apache.jena.shacl.lib.G; import org.apache.jena.shacl.validation.ReportItem; import org.apache.jena.shacl.vocabulary.SHACL; @@ -65,7 +65,7 @@ public ReportItem validate(ValidationContext vCxt, Graph data, Node focusNode) { return new ReportItem(msg, focusNode); } - List types = G.listAllTypesOfNode(data, focusNode); + Collection types = G.allTypesOfNodeRDFS(data, focusNode); if ( types.contains(expectedClass) ) return null; String msg = toString()+": Expected class :"+displayStr(expectedClass)+" for "+displayStr(focusNode); diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClosedConstraint.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClosedConstraint.java index 6e0fbe30d3e..ddcfc3dad08 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClosedConstraint.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ClosedConstraint.java @@ -18,7 +18,8 @@ package org.apache.jena.shacl.engine.constraint; -import static org.apache.jena.shacl.compact.writer.CompactOut.*; +import static org.apache.jena.shacl.compact.writer.CompactOut.compactArrayNodes; +import static org.apache.jena.shacl.compact.writer.CompactOut.compactUnquotedString; import static org.apache.jena.shacl.lib.ShLib.displayStr; import java.util.*; @@ -27,16 +28,16 @@ import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; import org.apache.jena.graph.Triple; +import org.apache.jena.riot.other.G; import org.apache.jena.riot.out.NodeFormatter; import org.apache.jena.shacl.engine.ValidationContext; -import org.apache.jena.shacl.lib.G; -import org.apache.jena.shacl.lib.GN; import org.apache.jena.shacl.parser.Constraint; import org.apache.jena.shacl.parser.ShaclParseException; import org.apache.jena.shacl.parser.Shape; import org.apache.jena.shacl.vocabulary.SHACL; import org.apache.jena.sparql.path.Path; import org.apache.jena.sparql.path.PathFactory; +import org.apache.jena.sparql.util.graph.GNode; import org.apache.jena.sparql.util.graph.GraphList; /** sh:closed */ @@ -61,7 +62,7 @@ private static List ignoredProperties(Graph shapesGraph, Node shNode) { if ( G.contains(shapesGraph, shNode, SHACL.ignoredProperties, null) ) { Node ignored = G.getOneSP(shapesGraph, shNode, SHACL.ignoredProperties); if ( ignored != null ) { - ignoredProperties = GraphList.members(GN.create(shapesGraph, ignored)) ; + ignoredProperties = GraphList.members(GNode.create(shapesGraph, ignored)) ; ignoredProperties.forEach(p->{ if ( ! p.isURI() ) throw new ShaclParseException("Only URIs allowed in sh:ignoredProperties at "+displayStr(shNode)); diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ConstraintPairwise.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ConstraintPairwise.java index fb04278b6d4..c7aa59dfc20 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ConstraintPairwise.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/ConstraintPairwise.java @@ -24,8 +24,8 @@ import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; +import org.apache.jena.riot.other.G; import org.apache.jena.shacl.engine.ValidationContext; -import org.apache.jena.shacl.lib.G; import org.apache.jena.shacl.parser.Constraint; import org.apache.jena.shacl.parser.Shape; import org.apache.jena.sparql.expr.ExprNotComparableException; diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/MaxCount.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/MaxCount.java index 116656683a8..10f0876f5f9 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/MaxCount.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/MaxCount.java @@ -19,6 +19,7 @@ package org.apache.jena.shacl.engine.constraint; import org.apache.jena.atlas.io.IndentedWriter; +import org.apache.jena.atlas.lib.InternalErrorException; import org.apache.jena.graph.Node; import org.apache.jena.riot.out.NodeFormatter; import org.apache.jena.shacl.vocabulary.SHACL; @@ -40,9 +41,11 @@ public Node getComponent() { return SHACL.MaxCountConstraintComponent; } - // Special syntax. Do nothing is called generally. + // Special syntax. Handled in ShapeOutputVisitor @Override - public void printCompact(IndentedWriter out, NodeFormatter nodeFmt) {} + public void printCompact(IndentedWriter out, NodeFormatter nodeFmt) { + throw new InternalErrorException("Call to MaxCount/compact syntax"); + } @Override public String toString() { diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/MinCount.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/MinCount.java index e725de711db..99936106a82 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/MinCount.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/MinCount.java @@ -19,6 +19,7 @@ package org.apache.jena.shacl.engine.constraint; import org.apache.jena.atlas.io.IndentedWriter; +import org.apache.jena.atlas.lib.InternalErrorException; import org.apache.jena.graph.Node; import org.apache.jena.riot.out.NodeFormatter; import org.apache.jena.shacl.vocabulary.SHACL; @@ -39,9 +40,11 @@ public Node getComponent() { return SHACL.MinCountConstraintComponent; } - // Special syntax. Do nothing is called generally. + // Special syntax. Handled in ShapeOutputVisitor property shape. Ignore here. @Override - public void printCompact(IndentedWriter out, NodeFormatter nodeFmt) {} + public void printCompact(IndentedWriter out, NodeFormatter nodeFmt) { + throw new InternalErrorException("Call to MinCount/compact syntax"); + } @Override public String toString() { diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/QualifiedValueShape.java b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/QualifiedValueShape.java index 9dc8ddcb0bb..0b80280042a 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/QualifiedValueShape.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/QualifiedValueShape.java @@ -23,13 +23,13 @@ import org.apache.jena.atlas.io.IndentedWriter; import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; +import org.apache.jena.riot.other.G; import org.apache.jena.riot.out.NodeFormatter; import org.apache.jena.shacl.ShaclException; import org.apache.jena.shacl.ValidationReport; import org.apache.jena.shacl.compact.writer.CompactOut; import org.apache.jena.shacl.compact.writer.CompactWriter; import org.apache.jena.shacl.engine.ValidationContext; -import org.apache.jena.shacl.lib.G; import org.apache.jena.shacl.parser.Constraint; import org.apache.jena.shacl.parser.Shape; import org.apache.jena.shacl.validation.ValidationProc; diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/lib/G.java b/jena-shacl/src/main/java/org/apache/jena/shacl/lib/G.java deleted file mode 100644 index 45e60d7c3c3..00000000000 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/lib/G.java +++ /dev/null @@ -1,371 +0,0 @@ -/* - * 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.shacl.lib; - -import java.util.*; - -import org.apache.jena.atlas.iterator.Iter; -import org.apache.jena.graph.Graph; -import org.apache.jena.graph.Node; -import org.apache.jena.graph.Triple; -import org.apache.jena.riot.out.NodeFmtLib; -import org.apache.jena.shacl.sys.C; -import org.apache.jena.sparql.util.graph.GNode; -import org.apache.jena.sparql.util.graph.GraphList; -import org.apache.jena.util.iterator.ExtendedIterator; - -/** Library of functions for convenience working directly with Graph and Node. */ -public class G { - - // Node versions - public static Node subject(Triple triple) { - return triple == null ? null : triple.getSubject(); - } - - public static Node predicate(Triple triple) { - return triple == null ? null : triple.getPredicate(); - } - - public static Node object(Triple triple) { - return triple == null ? null : triple.getObject(); - } - - // Node filter tests. - public static boolean isURI(Node n) { return n != null && n.isURI(); } - public static boolean isBlank(Node n) { return n != null && n.isBlank(); } - public static boolean isLiteral(Node n) { return n != null && n.isLiteral(); } - public static boolean isResource(Node n) { return n != null && (n.isURI()||n.isBlank()); } - - // Has type or is rdfs:subclassOf. - public static boolean isOfType(Graph graph, Node x, Node type) { - Objects.requireNonNull(x, "Subject"); - Objects.requireNonNull(type, "Type"); - List allClasses = listSubClasses(graph, type); - for ( Node c : allClasses ) { - if ( hasType(graph, x, c) ) - return true; - } - return false; - } - - public static boolean hasType(Graph graph, Node x, Node type) { - Objects.requireNonNull(x, "Subject"); - Objects.requireNonNull(type, "Type"); - return contains(graph, x, C.rdfType, type); - } - - public static Node getSP(Graph graph, Node s, Node p) { - return object(first(find(graph, s, p, Node.ANY))); - } - - public static List listSP(Graph graph, Node s, Node p) { - return iterSP(graph, s, p).toList(); - } - - public static long countSP(Graph graph, Node s, Node p) { - return Iter.count(iterSP(graph, s, p)); - } - - public static ExtendedIterator iterSP(Graph graph, Node s, Node p) { - return graph.find(s, p, null).mapWith(Triple::getObject); - } - - public static ExtendedIterator iterPO(Graph graph, Node p, Node o) { - return graph.find(null, p, o).mapWith(Triple::getSubject); - } - - - public static List listPO(Graph graph, Node p, Node o) { - return iterPO(graph, p, o).toList(); - } - - public static long countPO(Graph graph, Node p, Node o) { - return Iter.count(iterPO(graph, p, o)); - } - - public static List listSubjectsOfType(Graph graph, Node type) { - return graph.find(null, C.rdfType, type).mapWith(Triple::getSubject).toList(); - } - - public static List rdfList(Graph graph, Node node) { - GNode gNode = GN.create(graph, node); - return GraphList.members(gNode); - } - - // Follows RDFS - - /** - * List the subclasses of a type, including itself. - * This is ?x rdfs:subClassOf* type. - * The list does not contain duplicates. - */ - public static List listSubClasses(Graph graph, Node type) { - List acc = new ArrayList<>(); - // Subclasses are follow rdfs:subclassOf in reverse - object to subject. - // Transitive.transitive is "visit once". - Transitive.transitiveInc(graph, false, type, C.rdfsSubclassOf, acc); - return acc; - } - - /** - * List the superclasses of a type, including itself. - * This is type rdfs:subClassOf* ?x. - * The list does not contain duplicates. - */ - public static List listSuperClasses(Graph graph, Node type) { - List acc = new ArrayList<>(); - // Super classes are follow rdfs:subclassOf - subject to object. - // Transitive.transitive is "visit once". - Transitive.transitiveInc(graph, true, type, C.rdfsSubclassOf, acc); - return acc; - } - - public static List listNodesOfType(Graph graph, Node type) { - return graph.find(null, C.rdfType, type).mapWith(Triple::getSubject).toList(); - } - - /** List the types of a node/subject */ - public static List listTypesOfNode(Graph graph, Node subject) { - return graph.find(subject, C.rdfType, null).mapWith(Triple::getObject).toList(); - } - - /** List the types of a node/subject, following rdfs:subClassOf for super classes. */ - public static List listAllTypesOfNode(Graph graph, Node subject) { - List types = listTypesOfNode(graph, subject); - List types2 = new ArrayList<>(); - types.forEach(t->{ - List subClasses = listSuperClasses(graph, t); - types2.addAll(subClasses); - }); - return types2; - } - - /** List all the node of type, including considering rdfs:subClassOf */ - public static List listAllNodesOfType(Graph graph, Node type) { - List types = listSubClasses(graph, type); - List nodes = new ArrayList<>(); - types.forEach(t->nodes.addAll(listNodesOfType(graph, t))); - return nodes; - } - - // Set versions. - - public static Set setNodesOfType(Graph graph, Node type) { - return graph.find(null, C.rdfType, type).mapWith(Triple::getSubject).toSet(); - } - - /** Set of types of a node/subject */ - public static Set typesOfNode(Graph graph, Node subject) { - return graph.find(subject, C.rdfType, null).mapWith(Triple::getObject).toSet(); - } - - /** - * Set of the subclasses of a type, including itself. - * This is ?x rdfs:subClassOf* type. - */ - public static Set subClasses(Graph graph, Node type) { - Set acc = new HashSet<>(); - // Subclasses are follow rdfs:subclassOf in reverse - object to subject. - Transitive.transitiveInc(graph, false, type, C.rdfsSubclassOf, acc); - return acc; - } - - /** @deprecated Use {@link #allNodesOfType} */ - @Deprecated - public static Set setAllNodesOfType(Graph graph, Node type) { return allNodesOfType(graph, type); } - - /** @deprecated Use {@link #allSP} */ - @Deprecated - public static Set setAllSP(Graph graph, Node s, Node p) { - return allSP(graph, s, p); - } - - /** @deprecated Use {@link #allPO} */ - @Deprecated - public static Set setPO(Graph graph, Node p, Node o) { - return allPO(graph, p, o); - } - - /** List all the node of type, including considering rdfs:subClassOf */ - public static Set allNodesOfType(Graph graph, Node type) { - Set types = subClasses(graph, type); - Set nodes = new HashSet<>(); - types.forEach(t->nodes.addAll(listNodesOfType(graph, t))); - return nodes; - } - - public static Set allSP(Graph graph, Node s, Node p) { - return graph.find(s, p, null).mapWith(Triple::getObject).toSet(); - } - - public static Set allPO(Graph graph, Node p, Node o) { - return graph.find(null, p, o).mapWith(Triple::getSubject).toSet(); - } - - // Exactly one, exception on none or more than one. - public static Node getOneSP(Graph graph, Node s, Node p) { - return object(findUnique(graph, s, p, Node.ANY)); - } - - // Zero or one, exception on more than one. - public static Node getZeroOrOneSP(Graph graph, Node s, Node p) { - return object(findZeroOne(graph, s, p, Node.ANY)); - } - - // Exactly one, exception on none or more than one. - public static Node getOnePO(Graph graph, Node p, Node o) { - return subject(findUnique(graph, Node.ANY, p, o)); - } - - // Zero or one, exception on more than one. - public static Node getZeroOrOnePO(Graph graph, Node p, Node o) { - return subject(findZeroOne(graph, Node.ANY, p, o)); - } - - // Exactly one, exception on none or more than one. - public static Triple getOne(Graph graph, Node s, Node p, Node o) { - return findUnique(graph, s, p, Node.ANY); - } - - // Zero or one, exception on more than one. - // Can call object() or subject(). - public static Triple getZeroOrOne(Graph graph, Node s, Node p, Node o) { - return findZeroOne(graph, s, p, o); - } - - - public static boolean contains(Graph g, Node s, Node p, Node o) { - return g.contains(s, p, o); - } - - public static boolean absentOrOne(Graph g, Node s, Node p, Node o) { - if ( ! g.contains(s, p, o) ) - return false; - long x = Iter.count(g.find(s,p,null)); - if ( x == 1 ) - return true; - throw new RDFDataException("More then one ("+x+") "+matchStr(s,p,o)); - } - - public static boolean containsOne(Graph g, Node s, Node p, Node o) { - return g.contains(s, p, o) && Iter.count(g.find(s,p,null)) == 1; - } - - public static boolean hasProperty(Graph g, Node s, Node p) { - return g.contains(s, p, null); - } - - public static long objectConnectiveness(Graph graph, Node object) { - return Iter.count(graph.find(null, null, object)); - } - - public static boolean oneConnected(Graph graph, Node object) { - ExtendedIterator iter = graph.find(null, null, object); - if ( ! iter.hasNext() ) - // Zero. - return false; - iter.next(); - if ( iter.hasNext() ) - // more than one - return false; - return true; - } - - public static ExtendedIterator find(Graph g, Node s, Node p, Node o) { - return g.find(s, p, o); - } - - private static Triple findUnique(Graph g, Node s, Node p, Node o) { - ExtendedIterator iter = g.find(s, p, o); - try { - if ( ! iter.hasNext() ) - throw new RDFDataException("No match : "+matchStr(s,p,o)); - Triple x = iter.next(); - if ( iter.hasNext() ) - throw new RDFDataException("More than one match : "+matchStr(s,p,o)); - return x; - } finally { iter.close(); } - } - - private static Triple findZeroOne(Graph g, Node s, Node p, Node o) { - ExtendedIterator iter = g.find(s, p, o); - try { - if ( ! iter.hasNext() ) - return null; - Triple x = iter.next(); - if ( iter.hasNext() ) { - //g.find(s, p, o).forEachRemaining(System.err::println); - throw new RDFDataException("More than one match : "+matchStr(s,p,o)); - } - return x; - } finally { iter.close(); } - } - - private static String matchStr(Node s, Node p, Node o) { - //return String.format("(%s %s %s)", s, p, o); - return "("+NodeFmtLib.strNodes(s,p,o)+")"; - } - - private static Triple first(ExtendedIterator iter) { - try { - if ( ! iter.hasNext() ) - return null; - return iter.next(); - } finally { iter.close(); } - } - - @SafeVarargs - public static boolean allNonNull(X ... objects) { - return countNonNulls(objects) == objects.length; - } - - @SafeVarargs - public static boolean exactlyOneSet(X ... objects) { - return countNonNulls(objects) == 1; - } - - @SafeVarargs - public static X atMostOne(X ... objects) { - int c = 0; - X x = null; - for ( X obj : objects ) { - if ( obj != null ) { - c++; - if ( c > 1 ) - throw new RDFDataException("ExactlyOne:"+Arrays.asList(objects)); - if ( x == null ) - x = obj; - } - } - // Exactly one. -// if ( x == null ) -// throw new RDFDataException("ExactlyOne: None"); - return x; - } - - @SafeVarargs - public static int countNonNulls(X ... objects) { - int x = 0; - for ( Object obj : objects ) { - if ( obj != null ) - x++; - } - return x; - } -} diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/lib/GN.java b/jena-shacl/src/main/java/org/apache/jena/shacl/lib/GN.java deleted file mode 100644 index 3b859dedadd..00000000000 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/lib/GN.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.shacl.lib; - -import org.apache.jena.graph.Graph; -import org.apache.jena.graph.Node; -import org.apache.jena.graph.Triple; -import org.apache.jena.sparql.util.graph.GNode; - -public class GN { - - // Node filter tests. -//public static boolean isURI(GNode n) { return n != null && isURI(n.getNode()); } -//public static boolean isBlank(GNode n) { return n != null && isBlank(n.getNode()); } -//public static boolean isLiteral(GNode n) { return n != null && isLiteral(n.getNode()); } -//public static boolean isResource(GNode n) { return n != null && isURI(n.getNode())||isBlank(n.getNode()); } - - - - public static GNode create(Graph graph, Node node) { - return new GNode(graph, node); - } - - public static GNode subject(Graph graph, Triple triple) { - return triple == null ? null : create(graph, triple.getSubject()); - } - - public static GNode predicate(Graph graph, Triple triple) { - return triple == null ? null : create(graph, triple.getPredicate()); - } - - public static GNode object(Graph graph, Triple triple) { - return triple == null ? null : create(graph, triple.getObject()); - } -} diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/lib/ShLib.java b/jena-shacl/src/main/java/org/apache/jena/shacl/lib/ShLib.java index ddf35473017..eed33f1054c 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/lib/ShLib.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/lib/ShLib.java @@ -50,6 +50,7 @@ import org.apache.jena.vocabulary.RDFS; import org.apache.jena.vocabulary.XSD; +/** Misc operations used in the jena-shacl module. */ public class ShLib { private static String PREFIXES = StrUtils.strjoinNL( diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/lib/Transitive.java b/jena-shacl/src/main/java/org/apache/jena/shacl/lib/Transitive.java deleted file mode 100644 index 5096defab85..00000000000 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/lib/Transitive.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.shacl.lib; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import org.apache.jena.graph.Graph; -import org.apache.jena.graph.Node; -import org.apache.jena.graph.Triple; - -public class Transitive { - - // ---- Transitive properties, including the start node. - public static void transitiveInc(Graph graph, boolean forward, Node node, Node predicate, Collection output) { - recurse(graph, forward, node, predicate, output); - } - - // ---- Transitive properties, excluding the start node unless in a cycle. - public static void transitiveExc(Graph graph, boolean forward, Node node, Node predicate, Collection output) { - Iterator iter = singleStep(graph, forward, node, predicate); - Set visited = new HashSet<>(); - for (; iter.hasNext();) { - Node n1 = iter.next() ; - recurse_1(graph, forward, 1, -1, n1, predicate, visited, output) ; - } - } - - // Extracted and simplified From PathEval/PathEngineSPARQL. - private static void recurse(Graph graph, boolean forward, Node node, Node predicate, Collection output) { - Set visited = new HashSet<>(); - recurse_1(graph, forward, 0, -1, node, predicate, visited, output); - } - - private static void recurse_1(Graph graph, boolean forward, int stepCount, int maxStepCount, Node node, Node predicate, Set visited, Collection output) { - if ( maxStepCount >= 0 && stepCount > maxStepCount ) - return ; - if ( !visited.add(node) ) - return ; - output.add(node); - Iterator iter1 = singleStep(graph, forward, node, predicate) ; - // For each step, add to results and recurse. - for (; iter1.hasNext();) { - Node n1 = iter1.next() ; - recurse_1(graph, forward, stepCount + 1, maxStepCount, n1, predicate, visited, output) ; - } - } - - // A single step of a transitive properties. - // Because for SP? or ?PO, no duplicates occur, so works for both strategies. - private static Iterator singleStep(Graph graph, boolean forward, Node node, Node property) { - if ( forward ) - return G.find(graph, node, property, Node.ANY).mapWith(Triple::getObject); - else - return G.find(graph, Node.ANY, property, node).mapWith(Triple::getSubject); - } -} diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ConstraintComponents.java b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ConstraintComponents.java index 601186ca38a..120ddfc4b81 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ConstraintComponents.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ConstraintComponents.java @@ -28,11 +28,12 @@ import org.apache.jena.ext.com.google.common.collect.Multimap; import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; +import org.apache.jena.riot.other.G; import org.apache.jena.shacl.engine.Parameter; import org.apache.jena.shacl.engine.SparqlConstraints; import org.apache.jena.shacl.engine.constraint.ConstraintComponentSPARQL; import org.apache.jena.shacl.engine.constraint.SparqlComponent; -import org.apache.jena.shacl.lib.G; + import org.apache.jena.shacl.vocabulary.SHACL; class ConstraintComponents { @@ -70,7 +71,7 @@ public static ConstraintComponents parseSparqlConstraintComponents(Graph shapesG // SHACL.SPARQLConstraintComponent is not a subclass of SHACL.ConstraintComponent // SHACL.SPARQLConstraintComponent is an instance of SHACL.ConstraintComponent. // Need to process by actual property present. - G.listAllNodesOfType(shapesGraph, SHACL.ConstraintComponent).forEach(sccNode->{ + G.allNodesOfTypeRDFS(shapesGraph, SHACL.ConstraintComponent).forEach(sccNode->{ SparqlComponent c = sparqlConstraintComponent(shapesGraph, sccNode); if ( c != null ) { for ( Parameter p : c.getParams() ) { @@ -106,7 +107,7 @@ public static List processShape(Graph shapesGraph, ConstraintCompone // Alternative approach // // Find all shapes uses the parameter. -// List shapes = G.find(shapesGraph, null, paramPath, null).mapWith(Triple::getSubject).toList(); +// List shapes = G1.find(shapesGraph, null, paramPath, null).mapWith(Triple::getSubject).toList(); Node shNode = shape.getShapeNode(); // All components with this parameter. diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Constraints.java b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Constraints.java index 5d75798abfc..44a058ed822 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Constraints.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Constraints.java @@ -28,9 +28,9 @@ import org.apache.jena.graph.Node; import org.apache.jena.graph.Triple; import org.apache.jena.rdf.model.impl.Util; +import org.apache.jena.riot.other.G; import org.apache.jena.shacl.engine.SparqlConstraints; import org.apache.jena.shacl.engine.constraint.*; -import org.apache.jena.shacl.lib.G; import org.apache.jena.shacl.lib.ShLib; import org.apache.jena.shacl.sys.C; import org.apache.jena.shacl.vocabulary.SHACL; diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Parameters.java b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Parameters.java index d11a9744b07..c6d0313cbc1 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Parameters.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Parameters.java @@ -27,9 +27,9 @@ import org.apache.jena.ext.com.google.common.collect.Multimap; import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; +import org.apache.jena.riot.other.G; import org.apache.jena.shacl.engine.Parameter; import org.apache.jena.shacl.engine.constraint.SparqlComponent; -import org.apache.jena.shacl.lib.G; import org.apache.jena.shacl.vocabulary.SHACL; public class Parameters { diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Shape.java b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Shape.java index 74c33d47daa..248c392fce7 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Shape.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Shape.java @@ -25,10 +25,10 @@ import org.apache.jena.atlas.io.IndentedWriter; import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; +import org.apache.jena.riot.other.G; import org.apache.jena.riot.out.NodeFormatter; import org.apache.jena.shacl.engine.Target; import org.apache.jena.shacl.engine.TargetOps; -import org.apache.jena.shacl.lib.G; import org.apache.jena.shacl.validation.Severity; public abstract class Shape { diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ShapesParser.java b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ShapesParser.java index ed8f49e7456..b4daec9cd4e 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ShapesParser.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ShapesParser.java @@ -18,8 +18,8 @@ package org.apache.jena.shacl.parser; +import static org.apache.jena.riot.other.G.*; import static org.apache.jena.shacl.engine.ShaclPaths.pathToString; -import static org.apache.jena.shacl.lib.G.*; import static org.apache.jena.shacl.lib.ShLib.displayStr; import static org.apache.jena.shacl.sys.C.rdfsClass; @@ -31,13 +31,14 @@ import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; import org.apache.jena.graph.Triple; +import org.apache.jena.riot.other.G; +import org.apache.jena.riot.other.RDFDataException; import org.apache.jena.shacl.Shapes; import org.apache.jena.shacl.engine.ShaclPaths; import org.apache.jena.shacl.engine.Target; import org.apache.jena.shacl.engine.TargetType; import org.apache.jena.shacl.engine.Targets; import org.apache.jena.shacl.engine.constraint.JLogConstraint; -import org.apache.jena.shacl.lib.G; import org.apache.jena.shacl.lib.ShLib; import org.apache.jena.shacl.sys.ShaclSystem; import org.apache.jena.shacl.validation.Severity; @@ -140,8 +141,8 @@ public static Collection parseShapes(Graph shapesGraph, Targets targets, /** Find all names for shapes with explicit type NodeShape or PropertyShape. */ public static Collection findDeclaredShapes(Graph shapesGraph) { Set declared = new HashSet<>(); - G.listAllNodesOfType(shapesGraph, SHACL.NodeShape).forEach(declared::add); - G.listAllNodesOfType(shapesGraph, SHACL.PropertyShape).forEach(declared::add); + G.allNodesOfTypeRDFS(shapesGraph, SHACL.NodeShape).forEach(declared::add); + G.allNodesOfTypeRDFS(shapesGraph, SHACL.PropertyShape).forEach(declared::add); return declared; } @@ -240,29 +241,33 @@ static Shape unshape(Graph shapesGraph, Node shapeNode) { return /** parse a shape during a parsing process */ /*package*/ static Shape parseShapeStep(Set traversed, Map parsed, Graph shapesGraph, Node shapeNode) { - // Called by Constraints - if ( parsed.containsKey(shapeNode) ) - return parsed.get(shapeNode); - // Loop detection. Do before parsing. - if ( traversed.contains(shapeNode) ) { + try { + // Called by Constraints + if ( parsed.containsKey(shapeNode) ) + return parsed.get(shapeNode); + // Loop detection. Do before parsing. + if ( traversed.contains(shapeNode) ) { // Log.error(ShapesParser.class, "Cycle detected : node "+ShLib.displayStr(shapeNode)); // throw new ShaclParseException("Shapes cycle detected : node "+ShLib.displayStr(shapeNode)); - ShaclSystem.systemShaclLogger.warn("Cycle detected : node "+ShLib.displayStr(shapeNode)); - // Put in a substitute shape. - return unshape(shapesGraph, shapeNode); + ShaclSystem.systemShaclLogger.warn("Cycle detected : node "+ShLib.displayStr(shapeNode)); + // Put in a substitute shape. + return unshape(shapesGraph, shapeNode); + } + + traversed.add(shapeNode); + Shape shape = parseShape$(traversed, parsed, shapesGraph, shapeNode); + parsed.put(shapeNode, shape); + traversed.remove(shapeNode); + return shape; + } catch (RDFDataException ex) { + throw new ShaclParseException(ex.getMessage()); } - - traversed.add(shapeNode); - Shape shape = parseShape$(traversed, parsed, shapesGraph, shapeNode); - parsed.put(shapeNode, shape); - traversed.remove(shapeNode); - return shape; } private static Shape parseShape$(Set traversed, Map parsed, Graph shapesGraph, Node shapeNode) { if ( DEBUG ) OUT.printf("Parse shape : %s\n", displayStr(shapeNode)); - boolean isDeactivated = absentOrOne(shapesGraph, shapeNode, SHACL.deactivated, NodeConst.nodeTrue); + boolean isDeactivated = contains(shapesGraph, shapeNode, SHACL.deactivated, NodeConst.nodeTrue); Collection targets = targets(shapesGraph, shapeNode); List constraints = Constraints.parseConstraints(shapesGraph, shapeNode, parsed, traversed); Severity severity = severity(shapesGraph, shapeNode); diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VLib.java b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VLib.java index 451fe3503ff..8b86e74ddb0 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VLib.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VLib.java @@ -18,18 +18,19 @@ package org.apache.jena.shacl.validation; -import static org.apache.jena.shacl.lib.G.isOfType; - -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import org.apache.jena.atlas.io.IndentedWriter; import org.apache.jena.atlas.lib.InternalErrorException; import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; +import org.apache.jena.riot.other.G; import org.apache.jena.shacl.engine.ShaclPaths; import org.apache.jena.shacl.engine.Target; import org.apache.jena.shacl.engine.ValidationContext; -import org.apache.jena.shacl.lib.G; import org.apache.jena.shacl.parser.Constraint; import org.apache.jena.shacl.parser.NodeShape; import org.apache.jena.shacl.parser.PropertyShape; @@ -166,7 +167,7 @@ public static Collection focusNodes(Graph data, Target target) { switch(target.getTargetType()) { case targetClass: case implicitClass: - return G.allNodesOfType(data, targetObj); + return G.allNodesOfTypeRDFS(data, targetObj); case targetNode: return Collections.singletonList(targetObj); case targetObjectsOf: @@ -190,7 +191,7 @@ public static boolean isFocusNode(Target target, Node node, Graph data) { switch (target.getTargetType()) { case targetClass: case implicitClass: - return isOfType(data, node, targetObject); + return G.isOfType(data, node, targetObject); case targetNode: return targetObject.equals(node); case targetObjectsOf: diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VR.java b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VR.java index be46cd9cd92..927f9a79864 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VR.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VR.java @@ -30,9 +30,9 @@ import org.apache.jena.rdf.model.*; import org.apache.jena.riot.Lang; import org.apache.jena.riot.RDFDataMgr; +import org.apache.jena.riot.other.G; import org.apache.jena.shacl.ValidationReport; import org.apache.jena.shacl.engine.ShaclPaths; -import org.apache.jena.shacl.lib.G; import org.apache.jena.shacl.sys.C; import org.apache.jena.shacl.vocabulary.SHACL; import org.apache.jena.shacl.vocabulary.SHACLM; diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ValidationProc.java b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ValidationProc.java index d7d64759fad..d4845675cfc 100644 --- a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ValidationProc.java +++ b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ValidationProc.java @@ -153,7 +153,7 @@ private static void plainValidationInternal(ValidationContext vCxt, Graph data, } // XXX VLib - // Make ValidationContext carry teh ShaclVAlidator to recurse on. + // Make ValidationContext carry the ShaclVAlidator to recurse on. // Recursion for shapes of shapes. "shape-expecting constraint parameters" public static void execValidateShape(ValidationContext vCxt, Graph data, Shape shape, Node focusNode) { VLib.validateShape(vCxt, data, shape, focusNode); diff --git a/jena-tdb/src/main/java/org/apache/jena/tdb/store/DatasetGraphTDB.java b/jena-tdb/src/main/java/org/apache/jena/tdb/store/DatasetGraphTDB.java index 714226914c2..6d23514af48 100644 --- a/jena-tdb/src/main/java/org/apache/jena/tdb/store/DatasetGraphTDB.java +++ b/jena-tdb/src/main/java/org/apache/jena/tdb/store/DatasetGraphTDB.java @@ -19,8 +19,6 @@ package org.apache.jena.tdb.store; -import static org.apache.jena.sparql.util.graph.GraphUtils.triples2quadsDftGraph ; - import java.util.Iterator ; import org.apache.jena.atlas.iterator.Iter ; @@ -31,6 +29,7 @@ import org.apache.jena.graph.Node ; import org.apache.jena.query.ReadWrite ; import org.apache.jena.query.TxnType; +import org.apache.jena.riot.other.G; import org.apache.jena.sparql.core.DatasetGraphTriplesQuads ; import org.apache.jena.sparql.core.Quad ; import org.apache.jena.sparql.core.Transactional ; @@ -78,7 +77,7 @@ public DatasetGraphTDB(TripleTable tripleTable, QuadTable quadTable, DatasetPref @Override protected Iterator findInDftGraph(Node s, Node p, Node o) - { return triples2quadsDftGraph(getTripleTable().find(s, p, o)) ; } + { return G.triples2quadsDftGraph(getTripleTable().find(s, p, o)) ; } @Override protected Iterator findInSpecificNamedGraph(Node g, Node s, Node p, Node o) diff --git a/jena-tdb/src/main/java/org/apache/jena/tdb/store/GraphTDB.java b/jena-tdb/src/main/java/org/apache/jena/tdb/store/GraphTDB.java index eac78d2dd34..924b4f17f58 100644 --- a/jena-tdb/src/main/java/org/apache/jena/tdb/store/GraphTDB.java +++ b/jena-tdb/src/main/java/org/apache/jena/tdb/store/GraphTDB.java @@ -29,7 +29,7 @@ import org.apache.jena.graph.GraphEvents ; import org.apache.jena.graph.Node ; import org.apache.jena.graph.Triple ; -import org.apache.jena.riot.other.GLib ; +import org.apache.jena.riot.other.G; import org.apache.jena.riot.system.RiotLib; import org.apache.jena.shared.PrefixMapping ; import org.apache.jena.sparql.core.DatasetGraph ; @@ -138,7 +138,7 @@ final public void close() { @Override protected ExtendedIterator graphUnionFind(Node s, Node p, Node o) { Iterator iterQuads = getDatasetGraphTDB().find(Quad.unionGraph, s, p, o) ; - Iterator iter = GLib.quads2triples(iterQuads) ; + Iterator iter = G.quads2triples(iterQuads) ; // Suppress duplicates after projecting to triples. // TDB guarantees that duplicates are adjacent. // See SolverLib.