From 2c1f02f8a1a74d28f1fcdb65c06727c02ba75395 Mon Sep 17 00:00:00 2001 From: Andy Seaborne Date: Sun, 2 Feb 2025 18:19:59 +0000 Subject: [PATCH] Update result set testing for triple terms --- .../apache/jena/sparql/exec/RowSetMem.java | 3 +- .../apache/jena/sparql/expr/NodeValue.java | 29 +- .../sparql/expr/nodevalue/NodeFunctions.java | 38 +- .../sparql/resultset/ResultSetCompare.java | 304 ++++----------- .../sparql/resultset/ResultSetCompare1.java | 346 +++++++++++++++++ .../jena/sparql/resultset/ResultsCompare.java | 301 +++++++++++++++ .../jena/sparql/syntax/ElementData.java | 6 +- .../java/org/apache/jena/sparql/util/Iso.java | 214 +++++------ .../apache/jena/sparql/util/IsoMatcher.java | 24 +- .../jena/sparql/util/NodeIsomorphismMap.java | 33 +- .../jena/sparql/util/NodeToLabelMap.java | 92 ++--- .../apache/jena/sparql/util/iso/BNodeIso.java | 87 +++++ .../jena/sparql/util/iso/IsoAlgRows.java | 272 ++++++++++++++ .../{IsoAlg.java => iso/IsoAlgTuple.java} | 212 +++++------ .../apache/jena/sparql/util/iso/IsoLib.java | 125 +++++++ .../jena/sparql/util/iso/IsoMapping.java | 67 ++++ .../arq/junit/sparql/tests/QueryEvalTest.java | 12 +- .../jena/atlas/data/DataBagExaminer.java | 17 +- .../jena/atlas/data/TestDistinctDataBag.java | 88 ++--- .../jena/atlas/data/TestDistinctDataNet.java | 133 +++---- .../jena/atlas/data/TestSortedDataBag.java | 101 ++--- .../atlas/data/TestThresholdPolicyCount.java | 19 +- .../riot/protobuf/TestProtobufResultSet.java | 8 +- .../jena/riot/resultset/TestResultSetIO.java | 6 +- .../jena/riot/thrift/TestThriftResultSet.java | 8 +- .../jena/sparql/AbstractTestAdditional.java | 4 +- .../java/org/apache/jena/sparql/TC_ARQ.java | 4 +- .../optimize/TestSemanticEquivalence.java | 6 +- .../engine/binding/TestBindingStreams.java | 96 ++--- .../sparql/engine/join/AbstractTestJoin.java | 4 +- .../sparql/engine/join/TestTableJoin.java | 4 +- .../jena/sparql/path/TestPathQuery.java | 9 +- .../jena/sparql/resultset/TestResultSet.java | 92 +++-- .../resultset/TestResultSetFormat1.java | 85 ++--- .../org/apache/jena/sparql/util/TS_Util.java | 1 - .../apache/jena/sparql/util/iso/TS_Iso.java | 32 ++ .../apache/jena/sparql/util/iso/TestIso.java | 71 ++++ .../jena/sparql/util/iso/TestIsoAlgRows.java | 351 ++++++++++++++++++ .../sparql/util/{ => iso}/TestIsoMatcher.java | 24 +- .../org/apache/jena/atlas/lib/ListUtils.java | 6 +- .../main/java/org/apache/jena/graph/Node.java | 7 +- .../TestServiceEnhancerCachedVsUncached.java | 22 +- .../apache/jena/fuseki/main/TestQuery.java | 7 +- .../service/TestCustomServiceExecutor.java | 17 +- .../jena/tdb1/solver/TestSolverTDB.java | 12 +- .../jena/tdb2/solver/TestSolverTDB.java | 14 +- 46 files changed, 2373 insertions(+), 1040 deletions(-) create mode 100644 jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultSetCompare1.java create mode 100644 jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultsCompare.java create mode 100644 jena-arq/src/main/java/org/apache/jena/sparql/util/iso/BNodeIso.java create mode 100644 jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoAlgRows.java rename jena-arq/src/main/java/org/apache/jena/sparql/util/{IsoAlg.java => iso/IsoAlgTuple.java} (63%) create mode 100644 jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoLib.java create mode 100644 jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoMapping.java create mode 100644 jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TS_Iso.java create mode 100644 jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TestIso.java create mode 100644 jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TestIsoAlgRows.java rename jena-arq/src/test/java/org/apache/jena/sparql/util/{ => iso}/TestIsoMatcher.java (94%) diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/exec/RowSetMem.java b/jena-arq/src/main/java/org/apache/jena/sparql/exec/RowSetMem.java index 81fdb73b2dd..fbf2e0bbcd6 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/exec/RowSetMem.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/exec/RowSetMem.java @@ -49,8 +49,8 @@ public static RowSetRewindable create(RowSet rowSet) { * @param other The other RowSetMem object */ private RowSetMem(RowSetMem other) { + // Share vars and rows but not the iterator. vars = other.vars; - // Share results (not the iterator). rows = other.rows; reset(); } @@ -61,7 +61,6 @@ private RowSetMem(RowSetMem other) { * necessary internal datastructures are shared. This operation destroys * (uses up) a RowSet object that is not an in-memory one. */ - private RowSetMem(RowSet other) { if ( other instanceof RowSetMem rsm ) { // See also the RowSetMem(RowSetMem) constructor. diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/NodeValue.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/NodeValue.java index 55113b49e92..8866abd4ae8 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/NodeValue.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/NodeValue.java @@ -253,37 +253,33 @@ public static NodeValue booleanReturn(boolean b) // ---------------------------------------------------------------- // ---- Construct NodeValue from graph nodes - public static NodeValue makeNode(Node n) - { + public static NodeValue makeNode(Node n) { return nodeToNodeValue(n); } - public static NodeValue makeNode(String lexicalForm, RDFDatatype dtype) - { + public static NodeValue makeNode(String lexicalForm, RDFDatatype dtype) { Node n = NodeFactory.createLiteralDT(lexicalForm, dtype); return NodeValue.makeNode(n); } // Convenience - knows that lang tags aren't allowed with datatypes. - public static NodeValue makeNode(String lexicalForm, String langTag, Node datatype) - { - String uri = (datatype==null) ? null : datatype.getURI(); - return makeNode(lexicalForm, langTag, uri); + public static NodeValue makeNode(String lexicalForm, String langTag, Node datatype) { + String uri = (datatype == null) ? null : datatype.getURI(); + return makeNode(lexicalForm, langTag, uri); } - public static NodeValue makeNode(String lexicalForm, String langTag, String datatype) - { + public static NodeValue makeNode(String lexicalForm, String langTag, String datatype) { if ( datatype != null && datatype.equals("") ) datatype = null; if ( langTag != null && datatype != null ) // raise?? - Log.warn(NodeValue.class, "Both lang tag and datatype defined (lexcial form '"+lexicalForm+"')"); + Log.warn(NodeValue.class, "Both lang tag and datatype defined (lexcial form '" + lexicalForm + "')"); Node n = null; if ( langTag != null ) n = NodeFactory.createLiteralLang(lexicalForm, langTag); - else if ( datatype != null) { + else if ( datatype != null ) { RDFDatatype dType = TypeMapper.getInstance().getSafeTypeByName(datatype); n = NodeFactory.createLiteralDT(lexicalForm, dType); } else @@ -366,21 +362,18 @@ public NodeValue eval(Binding binding, FunctionEnv env) // NodeValues are immutable so no need to duplicate. @Override - public Expr copySubstitute(Binding binding) - { + public Expr copySubstitute(Binding binding) { return this; } @Override - public Expr applyNodeTransform(NodeTransform transform) - { + public Expr applyNodeTransform(NodeTransform transform) { Node n = asNode(); n = transform.apply(n); return makeNode(n); } - public Node evalNode(Binding binding, ExecutionContext execCxt) - { + public Node evalNode(Binding binding, ExecutionContext execCxt) { return asNode(); } diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeFunctions.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeFunctions.java index 52144eccf11..0d04b2021fd 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeFunctions.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeFunctions.java @@ -38,7 +38,6 @@ import org.apache.jena.irix.IRIs; import org.apache.jena.irix.IRIx; import org.apache.jena.query.ARQ; -import org.apache.jena.rdf.model.impl.Util; import org.apache.jena.riot.out.NodeFmtLib; import org.apache.jena.riot.system.RiotLib; import org.apache.jena.sparql.expr.ExprEvalException; @@ -127,22 +126,31 @@ public static NodeValue sameTerm(NodeValue nv1, NodeValue nv2) { return NodeValue.booleanReturn(sameTerm(nv1.asNode(), nv2.asNode())); } + // Jena - up to Jena 4. + // Language tags were kept in the case form they were given as. + // Jena5 - language tags are canonicalised. + /** sameTerm(x,y) */ public static boolean sameTerm(Node node1, Node node2) { - if ( node1.equals(node2) ) - return true; - if ( Util.isLangString(node1) && Util.isLangString(node2) ) { - String lex1 = node1.getLiteralLexicalForm(); - String lex2 = node2.getLiteralLexicalForm(); - if ( !lex1.equals(lex2) ) - return false; - return node1.getLiteralLanguage().equalsIgnoreCase(node2.getLiteralLanguage()); - } - if ( node1.isTripleTerm() && node2.isTripleTerm() ) { - return sameTriples(node1.getTriple(), node2.getTriple()); - } - return false; - } + return node1.sameTermAs(node2); + } + +// /** sameTerm(x,y) */ +// public static boolean sameTerm(Node node1, Node node2) { +// if ( node1.equals(node2) ) +// return true; +// if ( Util.isLangString(node1) && Util.isLangString(node2) ) { +// String lex1 = node1.getLiteralLexicalForm(); +// String lex2 = node2.getLiteralLexicalForm(); +// if ( !lex1.equals(lex2) ) +// return false; +// return node1.getLiteralLanguage().equalsIgnoreCase(node2.getLiteralLanguage()); +// } +// if ( node1.isTripleTerm() && node2.isTripleTerm() ) { +// return sameTriples(node1.getTriple(), node2.getTriple()); +// } +// return false; +// } private static boolean sameTriples(Triple t1, Triple t2) { return sameTerm(t1.getSubject(), t2.getSubject()) diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultSetCompare.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultSetCompare.java index b18a48fd9f2..ebaa375bccc 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultSetCompare.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultSetCompare.java @@ -18,68 +18,23 @@ package org.apache.jena.sparql.resultset; -import java.util.*; - -import org.apache.jena.atlas.iterator.Iter; -import org.apache.jena.graph.Node; -import org.apache.jena.graph.Triple; +import org.apache.jena.atlas.lib.ListUtils; import org.apache.jena.query.ResultSet; import org.apache.jena.query.ResultSetFactory; import org.apache.jena.query.ResultSetRewindable; import org.apache.jena.rdf.model.Model; -import org.apache.jena.sparql.core.Var; -import org.apache.jena.sparql.engine.binding.Binding; import org.apache.jena.sparql.exec.RowSet; -import org.apache.jena.sparql.exec.RowSetRewindable; -import org.apache.jena.sparql.util.EqualityTest; -import org.apache.jena.sparql.util.Iso; -import org.apache.jena.sparql.util.NodeIsomorphismMap; -import org.apache.jena.sparql.util.NodeUtils; -/** Comparison of ResultSets. - * Note that reading ResultSets is destructive so consider using {@link ResultSetRewindable} - * from {@link ResultSetFactory#makeRewindable} +/** + * Comparison of ResultSets. + * Note that reading ResultSets is destructive so consider using {@link ResultSetRewindable} + * from {@link ResultSetFactory#makeRewindable}. + * + * @deprecated Use {@link ResultsCompare}. */ - +@Deprecated(forRemoval = true) public class ResultSetCompare { - /* This is from the DAWG test suite. - * Result set 1: - * --------------- - * | x | y | - * =============== - * | _:b0 | _:b1 | - * | _:b2 | _:b3 | - * | _:b1 | _:b0 | - * --------------- - * Result set 2: - * --------------- - * | x | y | - * =============== - * | _:b1 | _:b0 | - * | _:b3 | _:b2 | - * | _:b2 | _:b3 | - * --------------- - */ - -// private static String[] rs1$ = { -// "(resultset (?x ?y)", -// " (row (?x _:b0) (?y _:b1))", -// " (row (?x _:b2) (?y _:b3))", -// " (row (?x _:b1) (?y _:b0))", -// ")"}; -// private static String[] rs2$ = { -// "(resultset (?x ?y)", -// " (row (?x _:c1) (?y _:c0))", -// " (row (?x _:c3) (?y _:c2))", -// " (row (?x _:c2) (?y _:c3))", -// ")"}; -// - - // Limitations: - // This code does not do compare/isomorphism combined with value testing. - // It drops to graph isomorphism, which is term based. - /** Compare two result sets for equivalence. Equivalence means: * A row rs1 has one matching row in rs2, and vice versa. * A row is only matched once. @@ -98,27 +53,11 @@ public static boolean equalsByValue(ResultSet rs1, ResultSet rs2) { /** See {@link #equalsByValue(ResultSet, ResultSet)} */ public static boolean equalsByValue(RowSet rs1, RowSet rs2) { - if ( ! compareHeader(rs1, rs2) ) return false; - - RowSetRewindable rs1a = rs1.rewindable(); - RowSetRewindable rs2a = rs2.rewindable(); - - if ( equivalent(convert(rs1a), convert(rs2a), new BNodeIso(NodeUtils.sameValue)) ) - return true; - rs1a.reset(); - rs2a.reset(); - return isomorphic(rs1a, rs2a); - } - - public static boolean equalsByTest(Collection b1, Collection b2, EqualityTest match) - { - List rows1 = new ArrayList<>(b1); - List rows2 = new ArrayList<>(b2); - return equivalent(rows1, rows2, match); + return ResultsCompare.equalsByValue(rs1, rs2); } - - /** compare two result sets for equivalence. Equivalence means: + /** + * Compare two result sets for equivalence. Equivalence means: * A row rs1 has one matching row in rs2, and vice versa. * A row is only matched once. * Rows match if they have the same variables with the same values, @@ -132,22 +71,24 @@ public static boolean equalsByTest(Collection b1, Collection b */ public static boolean equalsByTerm(ResultSet rs1, ResultSet rs2) { - return equalsByTerm(RowSet.adapt(rs1), RowSet.adapt(rs2)); + return ResultsCompare.equalsByTerm(rs1, rs2); } - /** See {@link #equalsByTerm(ResultSet, ResultSet)} */ + /** + * Compare two result sets for equivalence. Equivalence means: + * A row rs1 has one matching row in rs2, and vice versa. + * A row is only matched once. + * Rows match if they have the same variables with the same values, + * bNodes must map to a consistent other bNodes. + * Term comparisons of nodes. + * + * Destructive - rs1 and rs2 are both read, possibly to exhaustion. + * @param rs1 + * @param rs2 + * @return true if they are equivalent + */ public static boolean equalsByTerm(RowSet rs1, RowSet rs2) { - if ( ! compareHeader(rs1, rs2) ) - return false; - - RowSetRewindable rs1a = rs1.rewindable(); - RowSetRewindable rs2a = rs2.rewindable(); - // Aligned rows - if ( equivalent(convert(rs1a), convert(rs2a), new BNodeIso(NodeUtils.sameNode)) ) - return true; - rs1a.reset(); - rs2a.reset(); - return isomorphic(rs1a, rs2a); + return ResultsCompare.equalsByTerm(rs1, rs2); } /** Compare two result sets for equivalence. Equivalence means: @@ -156,206 +97,97 @@ public static boolean equalsByTerm(RowSet rs1, RowSet rs2) { * bNodes must map to a consistent other bNodes. * Value comparisons of nodes. * - * Destructive - rs1 and rs2 are both read, possibly to exhaustion. * @param rs1 * @param rs2 * @return true if they are equivalent */ public static boolean equalsByValueAndOrder(ResultSet rs1, ResultSet rs2) { - return equalsByValueAndOrder(RowSet.adapt(rs1), RowSet.adapt(rs2)); + return ResultsCompare.equalsByValueAndOrder(rs1, rs2); } /** See {@link #equalsByValueAndOrder(ResultSet, ResultSet)} */ public static boolean equalsByValueAndOrder(RowSet rs1, RowSet rs2) { - if ( ! compareHeader(rs1, rs2) ) - return false; - return equivalentByOrder(convert(rs1) , convert(rs2), new BNodeIso(NodeUtils.sameValue)); + return ResultsCompare.equalsByValueAndOrder(rs1, rs2); } - /** compare two result sets for equivalence. Equivalence means: * Each row in rs1 matches the same index row in rs2. * Rows match if they have the same variables with the same values, * bNodes must map to a consistent other bNodes. * RDF term comparisons of nodes. * - * Destructive - rs1 and rs2 are both read, possibly to exhaustion. * @param rs1 * @param rs2 * @return true if they are equivalent */ public static boolean equalsByTermAndOrder(ResultSet rs1, ResultSet rs2) { - return equalsByTermAndOrder(RowSet.adapt(rs1), RowSet.adapt(rs2)); + return ResultsCompare.equalsByTermAndOrder(rs1, rs2); } /** See {@link #equalsByTermAndOrder(ResultSet, ResultSet)} */ public static boolean equalsByTermAndOrder(RowSet rs1, RowSet rs2) { - if ( ! compareHeader(rs1, rs2) ) - return false; - return equivalentByOrder(convert(rs1) , convert(rs2), new BNodeIso(NodeUtils.sameNode)); + return ResultsCompare.equalsByTermAndOrder(rs1, rs2); } - /** compare two result sets for exact equality equivalence. - * Exact equalitymeans: - * Each row in rs1 matches the same index row in rs2. - * Rows match if they have the same variables with the same values, - * bNodes must have same labels + /** + * Compare two result sets for exact equality equivalence and order. + * Blank nodes must have same labels. * - * Destructive - rs1 and rs2 are both read, possibly to exhaustion. * @param rs1 * @param rs2 * @return true if they are equivalent */ public static boolean equalsExact(ResultSet rs1, ResultSet rs2) { - return equalsExact(RowSet.adapt(rs1), RowSet.adapt(rs2)); + return ResultsCompare.equalsExact(rs1, rs2); } - /** See {@link #equalsExact(ResultSet, ResultSet)} */ - public static boolean equalsExact(RowSet rs1, RowSet rs2) { - if ( !compareHeader(rs1, rs2) ) - return false; - return equivalentByOrder(convert(rs1) , convert(rs2), NodeUtils.sameNode); - } - - /** Compare two result sets for bNode isomorphism equivalence. - * Only does RDF term comparison. + /** + * Compare two result sets for exact equality equivalence and order. + * Blank nodes must have same labels. + * + * @param rs1 + * @param rs2 + * @return true if they are equivalent */ - public static boolean isomorphic(ResultSet rs1, ResultSet rs2) { - Model m1 = RDFOutput.encodeAsModel(rs1); - Model m2 = RDFOutput.encodeAsModel(rs2); - return m1.isIsomorphicWith(m2); - } - - /** See {@link #isomorphic(ResultSet, ResultSet)} */ - public static boolean isomorphic(RowSet rs1, RowSet rs2) { - return isomorphic(ResultSet.adapt(rs1), ResultSet.adapt(rs2)); - } - - /** Compare two bindings, use the node equality test provided */ - static public boolean equal(Binding bind1, Binding bind2, EqualityTest test) { - if ( bind1 == bind2 ) - return true; - if ( bind1.size() != bind2.size() ) - return false; - // They are the same size so containment is enough. - if ( ! containedIn(bind1, bind2, test) ) return false; - return true; + public static boolean equalsExact(RowSet rs1, RowSet rs2) { + return ResultsCompare.equalsByTermAndOrder(rs1, rs2); } - static private boolean compareHeader(RowSet rs1, RowSet rs2) { + private static boolean compareHeader(RowSet rs1, RowSet rs2) { if ( rs1 == null && rs2 == null ) return true; if ( rs1 == null ) return false; if ( rs2 == null ) return false; - Set names1 = Set.copyOf(rs1.getResultVars()); - Set names2 = Set.copyOf(rs2.getResultVars()); - return names1.equals(names2); - } - - static private List convert(RowSet rs) { - return Iter.iter(rs).toList(); + return ListUtils.equalsUnordered(rs1.getResultVars(), rs2.getResultVars()); } - static private boolean equivalent(Collection rows1, Collection rows2, EqualityTest match) { - if ( rows1.size() != rows2.size() ) - return false; - for ( Binding row1 : rows1 ) { - // find in rows2. - Binding matched = null; - for ( Binding row2 : rows2 ) { - // NEED BACKTRACKING - if ( equal(row1, row2, match) ) { - matched = row2; - break; - } - } - - if ( matched == null ) - return false; - // Remove matching. - rows2.remove(matched); - } - return true; - } - - static private boolean equivalentByOrder(List rows1, List rows2, EqualityTest match) { - if ( rows1.size() != rows2.size() ) - return false; - - Iterator iter1 = rows1.iterator(); - Iterator iter2 = rows2.iterator(); - - while ( iter1.hasNext() ) - { - // Does not need backtracking because rows must - // align and so must variables in a row. - Binding row1 = iter1.next(); - Binding row2 = iter2.next(); - if ( !equal(row1, row2, match) ) - return false; - } - return true; + /* + * Compare two result sets for blank node isomorphism equivalence. Only does RDF + * term comparison. + * + * This method does not handle triple terms in results. + * + * @deprecated Use {@link #equalsByTerm(ResultSet, ResultSet)} */ + @Deprecated(forRemoval = true) + public static boolean isomorphic(ResultSet rs1, ResultSet rs2) { + Model m1 = RDFOutput.encodeAsModel(rs1); + Model m2 = RDFOutput.encodeAsModel(rs2); + return m1.isIsomorphicWith(m2); } - // Is bind1 contained in bind2? For every (var,value) in bind1, is it in bind2? - // Maybe more in bind2. - private static boolean containedIn(Binding bind1, Binding bind2, EqualityTest test) { - // There are about 100 ways to do this! - Iterator iter1 = bind1.vars(); - - while(iter1.hasNext()) { - Var v = iter1.next(); - Node n1 = bind1.get(v); - Node n2 = bind2.get(v); - if ( n2 == null ) - // v bound in bind1 and not in bind2. - return false; - if ( ! test.equal(n1, n2) ) - return false; - } - return true; + /** + * Compare two row sets for blank node isomorphism equivalence. Only does RDF + * term comparison. + * + * This method does not handle triple terms in results. + * + * @deprecated Use {@link #equalsByTerm(RowSet, RowSet)} + */ + @Deprecated(forRemoval = true) + public static boolean isomorphic(RowSet rs1, RowSet rs2) { + return isomorphic(ResultSet.adapt(rs1), ResultSet.adapt(rs2)); } - public static class BNodeIso implements EqualityTest - { - private NodeIsomorphismMap mapping; - private EqualityTest literalTest; - - public BNodeIso(EqualityTest literalTest) { - this.mapping = new NodeIsomorphismMap(); - this.literalTest = literalTest; - } - - @Override - public boolean equal(Node n1, Node n2) { - if ( n1 == null && n2 == null ) - return true; - if ( n1 == null ) - return false; - if ( n2 == null ) - return false; - - if ( n1.isURI() && n2.isURI() ) - return n1.equals(n2); - - if ( n1.isLiteral() && n2.isLiteral() ) - return literalTest.equal(n1, n2); - - if ( n1.isBlank() && n2.isBlank() ) - return Iso.nodeIso(n1, n2, mapping); - - if ( n1.isVariable() && n2.isVariable() ) - return mapping.makeIsomorphic(n1, n2); - - if ( n1.isTripleTerm() && n2.isTripleTerm() ) { - Triple t1 = n1.getTriple(); - Triple t2 = n2.getTriple(); - return Iso.tripleIso(t1, t2, mapping); - } - - return false; - } - } } diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultSetCompare1.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultSetCompare1.java new file mode 100644 index 00000000000..597a4d68982 --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultSetCompare1.java @@ -0,0 +1,346 @@ +/* + * 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.sparql.resultset; + +public class ResultSetCompare1{} +//import java.util.Iterator; +//import java.util.List; +//import java.util.Set; +// +//import org.apache.jena.atlas.iterator.Iter; +//import org.apache.jena.graph.Node; +//import org.apache.jena.query.ResultSet; +//import org.apache.jena.query.ResultSetFactory; +//import org.apache.jena.query.ResultSetRewindable; +//import org.apache.jena.sparql.core.Var; +//import org.apache.jena.sparql.engine.binding.Binding; +//import org.apache.jena.sparql.exec.RowSet; +//import org.apache.jena.sparql.util.EqualityTest; +//import org.apache.jena.sparql.util.NodeUtils; +//import org.apache.jena.sparql.util.iso.BNodeIso; +// +///** Comparison of ResultSets. +// * Note that reading ResultSets is destructive so consider using {@link ResultSetRewindable} +// * from {@link ResultSetFactory#makeRewindable} +// */ +// +//public class ResultSetCompare1 -- Original. +//{ +// /** Compare two result sets for equivalence. Equivalence means: +// * A row rs1 has one matching row in rs2, and vice versa. +// * A row is only matched once. +// * Rows match if they have the same variables with the same values. +// * bNodes must map to a consistent other bNodes. Value comparisons of nodes. +// * +// * Destructive - rs1 and rs2 are both read, possibly to exhaustion. +// * @param rs1 +// * @param rs2 +// * @return true if they are equivalent +// */ +// +// public static boolean equalsByValue(ResultSet rs1, ResultSet rs2) { +// return ResultsCompare.equalsByValue(rs1, rs2); +// } +// +// /** See {@link #equalsByValue(ResultSet, ResultSet)} */ +// public static boolean equalsByValue(RowSet rs1, RowSet rs2) { +// return ResultsCompare.equalsByValue(rs1, rs2); +// } +// +//// +//// public static boolean equalsByTest(Collection b1, Collection b2, EqualityTest match) +//// { +//// List rows1 = new ArrayList<>(b1); +//// List rows2 = new ArrayList<>(b2); +//// return equivalent(rows1, rows2, match); +//// } +//// +// /** compare two result sets for equivalence. Equivalence means: +// * A row rs1 has one matching row in rs2, and vice versa. +// * A row is only matched once. +// * Rows match if they have the same variables with the same values, +// * bNodes must map to a consistent other bNodes. +// * Term comparisons of nodes. +// * +// * Destructive - rs1 and rs2 are both read, possibly to exhaustion. +// * @param rs1 +// * @param rs2 +// * @return true if they are equivalent +// */ +// +// public static boolean equalsByTerm(ResultSet rs1, ResultSet rs2) { +// return ResultsCompare.equalsByTerm(rs1, rs2); +// } +// +// /** See {@link #equalsByTerm(ResultSet, ResultSet)} */ +// public static boolean equalsByTerm(RowSet rs1, RowSet rs2) { +// return ResultsCompare.equalsByTerm(rs1, rs2); +// } +// +// /** Compare two result sets for equivalence. Equivalence means: +// * Each row in rs1 matches the same index row in rs2. +// * Rows match if they have the same variables with the same values, +// * bNodes must map to a consistent other bNodes. +// * Value comparisons of nodes. +// * +// * Destructive - rs1 and rs2 are both read, possibly to exhaustion. +// * @param rs1 +// * @param rs2 +// * @return true if they are equivalent +// */ +// public static boolean equalsByValueAndOrder(ResultSet rs1, ResultSet rs2) { +// return equalsByValueAndOrder(RowSet.adapt(rs1), RowSet.adapt(rs2)); +// } +// +// /** See {@link #equalsByValueAndOrder(ResultSet, ResultSet)} */ +// public static boolean equalsByValueAndOrder(RowSet rs1, RowSet rs2) { +// if ( ! compareHeader(rs1, rs2) ) +// return false; +// return equivalentByOrder(convert(rs1) , convert(rs2), BNodeIso.bnodeIsoByValue()); +// } +// +// +// /** compare two result sets for equivalence. Equivalence means: +// * Each row in rs1 matches the same index row in rs2. +// * Rows match if they have the same variables with the same values, +// * bNodes must map to a consistent other bNodes. +// * RDF term comparisons of nodes. +// * +// * Destructive - rs1 and rs2 are both read, possibly to exhaustion. +// * @param rs1 +// * @param rs2 +// * @return true if they are equivalent +// */ +// public static boolean equalsByTermAndOrder(ResultSet rs1, ResultSet rs2) { +// return equalsByTermAndOrder(RowSet.adapt(rs1), RowSet.adapt(rs2)); +// } +// +// /** See {@link #equalsByTermAndOrder(ResultSet, ResultSet)} */ +// public static boolean equalsByTermAndOrder(RowSet rs1, RowSet rs2) { +// if ( ! compareHeader(rs1, rs2) ) +// return false; +// return equivalentByOrder(convert(rs1) , convert(rs2), BNodeIso.bnodeIsoByTerm()); +// } +// +// /** compare two result sets for exact equality equivalence. +// * Exact equality means: +// * Each row in rs1 matches the same index row in rs2. +// * Rows match if they have the same variables with the same values, +// * bNodes must have same labels +// * +// * Destructive - rs1 and rs2 are both read, possibly to exhaustion. +// * @param rs1 +// * @param rs2 +// * @return true if they are equivalent +// */ +// public static boolean equalsExact(ResultSet rs1, ResultSet rs2) { +// return equalsExact(RowSet.adapt(rs1), RowSet.adapt(rs2)); +// } +// +// /** Compare two list - unordered */ +// public static boolean equalsByTerm(List list1, List list2) { +// return ResultsCompare.equalsByTerm(list1, list2); +// } +// +// /** Compare two list - unordered */ +// public static boolean equalsExact(List list1, List list2) { +// return ResultsCompare.equalsExact(list1, list2); +// } +// +// /** +// * Compare two row sets for exact equality equivalence. +// * Exact equality means: +// * Each row in rs1 matches the same index row in rs2. +// * Rows match if they have the same variables with the same values, +// * bNodes must have same labels +// * +// * Destructive - rs1 and rs2 are both read, possibly to exhaustion. +// * @param rs1 +// * @param rs2 +// * @return true if they are equivalent +// */ +// public static boolean equalsExact(RowSet rs1, RowSet rs2) { +// if ( !compareHeader(rs1, rs2) ) +// return false; +// return equivalentByOrder(convert(rs1) , convert(rs2), NodeUtils.sameNode); +// } +// +//// +//// /** +//// * Compare two result sets for blank node isomorphism equivalence. +//// * Only does RDF term comparison. +//// * @deprecated Use {@link #equalsByTerm(ResultSet, ResultSet)} +//// */ +//// @Deprecated(forRemoval = true) +//// public static boolean isomorphic(ResultSet rs1, ResultSet rs2) { +//// Model m1 = RDFOutput.encodeAsModel(rs1); +//// Model m2 = RDFOutput.encodeAsModel(rs2); +//// return m1.isIsomorphicWith(m2); +//// } +//// +//// /** +//// * Compare two row sets for blank node isomorphism equivalence. +//// * Only does RDF term comparison. +//// * @deprecated Use {@link #equalsByTerm(RowSet, RowSet)} +//// */ +//// @Deprecated(forRemoval = true) +//// public static boolean isomorphic(RowSet rs1, RowSet rs2) { +//// return isomorphic(ResultSet.adapt(rs1), ResultSet.adapt(rs2)); +//// } +//// +// +// static private List convert(RowSet rs) { +// return Iter.iter(rs).toList(); +// } +// +// +// /** Compare two bindings, use the node equality test provided */ +// static public boolean equal(Binding bind1, Binding bind2, EqualityTest test) { +// if ( bind1 == bind2 ) +// return true; +// if ( bind1.size() != bind2.size() ) +// return false; +// // They are the same size so containment is enough. +// if ( ! containedIn(bind1, bind2, test) ) +// return false; +// return true; +// } +// +// static private boolean compareHeader(RowSet rs1, RowSet rs2) { +// if ( rs1 == null && rs2 == null ) +// return true; +// if ( rs1 == null ) +// return false; +// if ( rs2 == null ) +// return false; +// Set names1 = Set.copyOf(rs1.getResultVars()); +// Set names2 = Set.copyOf(rs2.getResultVars()); +// return names1.equals(names2); +// } +// +//// private static final boolean DEBUG = false; +//// +//// static private boolean equivalent(Collection rows1, Collection rows2, EqualityTest match) { +//// if ( rows1.size() != rows2.size() ) +//// return false; +//// for ( Binding row1 : rows1 ) { +//// if ( DEBUG ) System.out.println(" Row1 = "+row1); +//// +//// // find in rows2. +//// Binding matched = null; +//// int i = 0; +//// for ( Binding row2 : rows2 ) { +//// if ( DEBUG ) System.out.printf("%-2d Row2 = %s\n", i++, row2); +//// +//// // NEED BACKTRACKING +//// if ( equal(row1, row2, match) ) { +//// if ( DEBUG ) System.out.println("MATCHES"); +//// matched = row2; +//// break; +//// } +//// } +//// +//// if ( DEBUG ) System.out.println(); +//// if ( matched == null ) +//// return false; +//// // Remove matching. +//// rows2.remove(matched); +//// } +//// return true; +//// } +//// +// static private boolean equivalentByOrder(List rows1, List rows2, EqualityTest match) { +// if ( rows1.size() != rows2.size() ) +// return false; +// +// Iterator iter1 = rows1.iterator(); +// Iterator iter2 = rows2.iterator(); +// +// while ( iter1.hasNext() ) +// { +// // Does not need backtracking because rows must +// // align and so must variables in a row. +// Binding row1 = iter1.next(); +// Binding row2 = iter2.next(); +// if ( !equal(row1, row2, match) ) +// return false; +// } +// return true; +// } +// +// // Is bind1 contained in bind2? For every (var,value) in bind1, is it in bind2? +// // Maybe more in bind2. +// private static boolean containedIn(Binding bind1, Binding bind2, EqualityTest test) { +// // There are about 100 ways to do this! +// Iterator iter1 = bind1.vars(); +// +// while(iter1.hasNext()) { +// Var v = iter1.next(); +// Node n1 = bind1.get(v); +// Node n2 = bind2.get(v); +// if ( n2 == null ) +// // v bound in bind1 and not in bind2. +// return false; +// if ( ! test.equal(n1, n2) ) +// return false; +// } +// return true; +// } +//// +//// public static class BNodeIso implements EqualityTest +//// { +//// private NodeIsomorphismMap mapping; +//// private EqualityTest literalTest; +//// +//// public BNodeIso(EqualityTest literalTest) { +//// this.mapping = new NodeIsomorphismMap(); +//// this.literalTest = literalTest; +//// } +//// +//// @Override +//// public boolean equal(Node n1, Node n2) { +//// if ( n1 == null && n2 == null ) +//// return true; +//// if ( n1 == null ) +//// return false; +//// if ( n2 == null ) +//// return false; +//// +//// if ( n1.isURI() && n2.isURI() ) +//// return n1.equals(n2); +//// +//// if ( n1.isLiteral() && n2.isLiteral() ) +//// return literalTest.equal(n1, n2); +//// +//// if ( n1.isBlank() && n2.isBlank() ) +//// return Iso.nodeIso(n1, n2, mapping); +//// +//// if ( n1.isVariable() && n2.isVariable() ) +//// return mapping.makeIsomorphic(n1, n2); +//// +//// if ( n1.isTripleTerm() && n2.isTripleTerm() ) { +//// Triple t1 = n1.getTriple(); +//// Triple t2 = n2.getTriple(); +//// return Iso.tripleIso(t1, t2, mapping); +//// } +//// +//// return false; +//// } +//// } +//} diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultsCompare.java b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultsCompare.java new file mode 100644 index 00000000000..f5e77265484 --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/sparql/resultset/ResultsCompare.java @@ -0,0 +1,301 @@ +/* + * 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.sparql.resultset; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.apache.jena.atlas.iterator.Iter; +import org.apache.jena.graph.Node; +import org.apache.jena.query.ResultSet; +import org.apache.jena.query.ResultSetFactory; +import org.apache.jena.query.ResultSetRewindable; +import org.apache.jena.sparql.core.Var; +import org.apache.jena.sparql.engine.binding.Binding; +import org.apache.jena.sparql.exec.RowSet; +import org.apache.jena.sparql.util.EqualityTest; +import org.apache.jena.sparql.util.NodeUtils; +import org.apache.jena.sparql.util.iso.BNodeIso; +import org.apache.jena.sparql.util.iso.IsoAlgRows; + +/** Comparison of ResultSets. + * Note that reading ResultSets is destructive so consider using {@link ResultSetRewindable} + * from {@link ResultSetFactory#makeRewindable} + */ + +public class ResultsCompare { + + /** + * Compare two result sets for equivalence where nodes are compared by value. A + * row rs1 has one matching row in rs2, and vice versa. A row is only matched + * once. Rows match if they have the same variables with the same values. bNodes + * must map to a consistent other bNodes. Value comparisons of nodes. + * + * @param rs1 + * @param rs2 + * @return true if they are equivalent + */ + public static boolean equalsByValue(ResultSet rs1, ResultSet rs2) { + return equalsByValue(RowSet.adapt(rs1), RowSet.adapt(rs2)); + } + + /** See {@link #equalsByValue(ResultSet, ResultSet)} */ + public static boolean equalsByValue(RowSet rs1, RowSet rs2) { + return IsoAlgRows.isIsomorphic(rs1, rs2, BNodeIso.Match.BNODES_VALUE); + } + + /** + * Compare two result sets for equivalence where nodes are compared by beign the + * same term.. A row rs1 has one matching row in rs2, and vice versa. A row is + * only matched once. Rows match if they have the same variables with the same + * values, bNodes must map to a consistent other bNodes. + * + * @param rs1 + * @param rs2 + * @return true if they are equivalent + */ + public static boolean equalsByTerm(ResultSet rs1, ResultSet rs2) { + return equalsByTerm(RowSet.adapt(rs1), RowSet.adapt(rs2)); + } + + /** + * Compare two row sets for equivalence. Equivalence means: + * A row rs1 has one matching row in rs2, and vice versa. + * A row is only matched once. + * Rows match if they have the same variables with the same values, + * blank node must map to a consistent blank node in the other row set. + * Term comparisons of nodes. + * + * Destructive - rs1 and rs2 are both read, possibly to exhaustion. + * @param rs1 + * @param rs2 + * @return true if they are equivalent + */ + public static boolean equalsByTerm(RowSet rs1, RowSet rs2) { + return IsoAlgRows.isIsomorphic(rs1, rs2, BNodeIso.Match.BNODES_TERM); + } + + /** Compare two list - unordered */ + public static boolean equalsByTerm(List list1, List list2) { + return IsoAlgRows.isIsomorphic(list1, list2, BNodeIso.Match.BNODES_TERM); + } + + /** + * Compare two result sets for equivalence. Equivalence means: Each row in rs1 + * matches the same index row in rs2. Rows match if they have the same variables + * with the same values, bNodes must map to a consistent other bNodes. + * Destructive - rs1 and rs2 are both read, possibly to exhaustion. + * + * @param rs1 + * @param rs2 + * @return true if they are equivalent + */ + public static boolean equalsByValueAndOrder(ResultSet rs1, ResultSet rs2) { + return equalsByValueAndOrder(RowSet.adapt(rs1), RowSet.adapt(rs2)); + } + + /** + * Compare two result sets for equivalence. Equivalence means: Each row in rs1 + * matches the same index row in rs2. Rows match if they have the same variables + * with the same values, bNodes must map to a consistent other bNodes. + * Destructive - rs1 and rs2 are both read, possibly to exhaustion. + * + * @param rs1 + * @param rs2 + * @return true if they are equivalent + */ + public static boolean equalsByValueAndOrder(RowSet rs1, RowSet rs2) { + if ( ! compareHeader(rs1, rs2) ) + return false; + return equivalentByOrder(convert(rs1) , convert(rs2), BNodeIso.bnodeIsoByValue()); + } + + /** + * Compare two result sets for equivalence. + * Equivalence means: Each row in rs1 + * matches the same index row in rs2. Rows match if they have the same variables + * with the same values, blank nodes must map to a consistent other blank node. + * RDF term comparisons of nodes. + * Destructive - rs1 and rs2 are both read, possibly to exhaustion. + * + * @param rs1 + * @param rs2 + * @return true if they are equivalent + */ + public static boolean equalsByTermAndOrder(ResultSet rs1, ResultSet rs2) { + return equalsByTermAndOrder(RowSet.adapt(rs1), RowSet.adapt(rs2)); + } + + /** + * Compare two row sets for equivalence. + * Equivalence means: Each row in rs1 + * matches the same index row in rs2. Rows match if they have the same variables + * with the same values, blank nodes must map to a consistent other blank node. + * RDF term comparisons of nodes. + * Destructive - rs1 and rs2 are both read, possibly to exhaustion. + * + * @param rs1 + * @param rs2 + * @return true if they are equivalent + */ + public static boolean equalsByTermAndOrder(RowSet rs1, RowSet rs2) { + if ( ! compareHeader(rs1, rs2) ) + return false; + return equivalentByOrder(convert(rs1) , convert(rs2), BNodeIso.bnodeIsoByTerm()); + } + + /** + * Compare two result sets for exact equality equivalence. + * Exact equality means: + * Each row in rs1 matches the same index row in rs2. + * Rows match if they have the same variables with the same values, + * Blank nodes must have same labels + * + * Destructive - rs1 and rs2 are both read, possibly to exhaustion. + * @param rs1 + * @param rs2 + * @return true if they are equivalent + */ + public static boolean equalsExact(ResultSet rs1, ResultSet rs2) { + return equalsExact(RowSet.adapt(rs1), RowSet.adapt(rs2)); + } + + /** + * Compare two row sets for equivalence where blank nodes must have same labels + * Destructive - rs1 and rs2 are both read, possibly to exhaustion. + * + * @param rs1 + * @param rs2 + * @return true if they are equivalent + */ + public static boolean equalsExact(RowSet rs1, RowSet rs2) { + if ( !compareHeader(rs1, rs2) ) + return false; + return equalsExact(convert(rs1), convert(rs2)); + } + + /** + * Compare two row sets for exact node equality equivalence. + * Each row in rs1 matches some other row in rs2. + * Rows match if they have the same variables with the same terms. + * Blank nodes must have same labels + * + * @param list1 + * @param list2 + * @return true if they are equivalent + */ + public static boolean equalsExact(List list1, List list2) { + // Mutable copy used to track matches from list1. + // This would also work. + // return IsoAlgRows.isIsomorphic(list1, list2, BNodeIso.Match.EXACT); + // The code here is simpel and direct. + + list2 = new ArrayList<>(list2); + if ( list1.size() != list2.size() ) + return false; + for ( Binding binding : list1 ) { + boolean wasPresent = list2.remove(binding); + if ( ! wasPresent ) + return false; + } + // list2 must be empty. + return true; + } + + /** + * Compare two row sets for exact node equality equivalence. + * Each row in rs1 matches the same row in rs2. + * Rows match if they have the same variables with the same values, + * Blank nodes must have same labels + * + * @param list1 + * @param list2 + * @return true if they are equivalent + */ + public static boolean equalsExactAndOrder(List list1, List list2) { + return equivalentByOrder(list1, list2, NodeUtils.sameRdfTerm); + } + + /** Compare two bindings, use the node equality test provided */ + static public boolean equal(Binding bind1, Binding bind2, EqualityTest test) { + if ( bind1 == bind2 ) + return true; + if ( bind1.size() != bind2.size() ) + return false; + // They are the same size so containment is enough. + if ( ! containedIn(bind1, bind2, test) ) + return false; + return true; + } + + static private boolean compareHeader(RowSet rs1, RowSet rs2) { + if ( rs1 == null && rs2 == null ) + return true; + if ( rs1 == null ) + return false; + if ( rs2 == null ) + return false; + Set names1 = Set.copyOf(rs1.getResultVars()); + Set names2 = Set.copyOf(rs2.getResultVars()); + return names1.equals(names2); + } + + static private List convert(RowSet rs) { + return Iter.iter(rs).toList(); + } + + static private boolean equivalentByOrder(List rows1, List rows2, EqualityTest match) { + if ( rows1.size() != rows2.size() ) + return false; + + Iterator iter1 = rows1.iterator(); + Iterator iter2 = rows2.iterator(); + + while (iter1.hasNext()) { + // Does not need backtracking because rows must + // align and so must variables in a row. + Binding row1 = iter1.next(); + Binding row2 = iter2.next(); + if ( !equal(row1, row2, match) ) + return false; + } + return true; + } + + // Is bind1 contained in bind2? For every (var,value) in bind1, is it in bind2? + // Maybe more in bind2. + private static boolean containedIn(Binding bind1, Binding bind2, EqualityTest test) { + // There are about 100 ways to do this! + Iterator iter1 = bind1.vars(); + + while(iter1.hasNext()) { + Var v = iter1.next(); + Node n1 = bind1.get(v); + Node n2 = bind2.get(v); + if ( n2 == null ) + // v bound in bind1 and not in bind2. + return false; + if ( ! test.equal(n1, n2) ) + return false; + } + return true; + } +} diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/syntax/ElementData.java b/jena-arq/src/main/java/org/apache/jena/sparql/syntax/ElementData.java index c82b967eafb..e58e1a5a980 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/syntax/ElementData.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/syntax/ElementData.java @@ -27,9 +27,8 @@ import org.apache.jena.sparql.algebra.table.TableData ; import org.apache.jena.sparql.core.Var ; import org.apache.jena.sparql.engine.binding.Binding ; -import org.apache.jena.sparql.resultset.ResultSetCompare ; +import org.apache.jena.sparql.resultset.ResultsCompare; import org.apache.jena.sparql.util.NodeIsomorphismMap ; -import org.apache.jena.sparql.util.NodeUtils ; public class ElementData extends Element { @@ -81,7 +80,8 @@ public boolean equalTo(Element el2, NodeIsomorphismMap isoMap) ElementData f2 = (ElementData)el2 ; if ( ! vars.equals(f2.vars) ) return false ; - if ( ! ResultSetCompare.equalsByTest(rows, f2.rows, new ResultSetCompare.BNodeIso(NodeUtils.sameNode)) ) + + if ( ! ResultsCompare.equalsByTerm(rows, f2.rows) ) return false ; return true ; } diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/Iso.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/Iso.java index c528fd62209..f8e17f5a99f 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/util/Iso.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/Iso.java @@ -34,165 +34,137 @@ */ public class Iso { - /* - * Are lists of triples isomorphic? - * The mapping policy {@link NodeIsomorphismMap} is mutated. + /** + * Are lists of triples isomorphic? The mapping policy {@link NodeIsomorphismMap} + * is mutated. */ public static boolean isomorphicTriples(List triples1, List triples2, NodeIsomorphismMap isoMap) { if ( triples1.size() != triples2.size() ) - return false ; + return false; for ( int i = 0 ; i < triples1.size() ; i++ ) { - Triple t1 = triples1.get(i) ; - Triple t2 = triples2.get(i) ; - if ( ! tripleIso(t1, t2, isoMap)) - return false ; + Triple t1 = triples1.get(i); + Triple t2 = triples2.get(i); + if ( !tripleIso(t1, t2, isoMap) ) + return false; } - return true ; + return true; } - /* - * Are lists of quads isomorphic? - * The mapping policy {@link NodeIsomorphismMap} is mutated. + /** + * Are lists of quads isomorphic? The mapping policy {@link NodeIsomorphismMap} + * is mutated. */ public static boolean isomorphicQuads(List quads1, List quads2, NodeIsomorphismMap isoMap) { if ( quads1.size() != quads2.size() ) - return false ; + return false; for ( int i = 0 ; i < quads1.size() ; i++ ) { - Quad q1 = quads1.get(i) ; - Quad q2 = quads2.get(i) ; - if ( ! quadIso(q1, q2, isoMap)) - return false ; + Quad q1 = quads1.get(i); + Quad q2 = quads2.get(i); + if ( !quadIso(q1, q2, isoMap) ) + return false; } - return true ; + return true; } - /* - * Are lists of nodes isomorphic? - * The mapping policy {@link NodeIsomorphismMap} is mutated. + /** + * Are lists of nodes isomorphic? The mapping policy {@link NodeIsomorphismMap} + * is mutated. */ public static boolean isomorphicNodes(List nodes1, List nodes2, NodeIsomorphismMap isoMap) { if ( nodes1.size() != nodes2.size() ) - return false ; + return false; for ( int i = 0 ; i < nodes1.size() ; i++ ) { - Node n1 = nodes1.get(i) ; - Node n2 = nodes2.get(i) ; - if ( ! nodeIso(n1, n2, isoMap)) - return false ; + Node n1 = nodes1.get(i); + Node n2 = nodes2.get(i); + if ( !nodeIso(n1, n2, isoMap) ) + return false; } - return true ; + return true; } - /* - * Are two triple paths isomorphic? - * The mapping policy {@link NodeIsomorphismMap} is mutated. + /** + * Are two triple paths isomorphic? The mapping policy {@link NodeIsomorphismMap} + * is mutated. */ - public static boolean triplePathIso(TriplePath tp1, TriplePath tp2, NodeIsomorphismMap isoMap) - { + public static boolean triplePathIso(TriplePath tp1, TriplePath tp2, NodeIsomorphismMap isoMap) { if ( tp1.isTriple() ^ tp2.isTriple() ) - return false ; + return false; if ( tp1.isTriple() ) - return Iso.tripleIso(tp1.asTriple(), tp2.asTriple(), isoMap) ; + return Iso.tripleIso(tp1.asTriple(), tp2.asTriple(), isoMap); else - return Iso.nodeIso(tp1.getSubject(), tp2.getSubject(), isoMap) && - Iso.nodeIso(tp1.getObject(), tp2.getObject(), isoMap) && - tp1.getPath().equalTo(tp2.getPath(), isoMap) ; + return Iso.nodeIso(tp1.getSubject(), tp2.getSubject(), isoMap) && Iso.nodeIso(tp1.getObject(), tp2.getObject(), isoMap) + && tp1.getPath().equalTo(tp2.getPath(), isoMap); } - /* - * Are two triples isomorphic? - * The mapping policy {@link NodeIsomorphismMap} is mutated. + /** + * Are two triples isomorphic? The mapping policy {@link NodeIsomorphismMap} is + * mutated. */ - public static boolean tripleIso(Triple t1, Triple t2, NodeIsomorphismMap labelMap) - { - Node s1 = t1.getSubject() ; - Node p1 = t1.getPredicate() ; - Node o1 = t1.getObject() ; - - Node s2 = t2.getSubject() ; - Node p2 = t2.getPredicate() ; - Node o2 = t2.getObject() ; - - if ( ! nodeIso(s1, s2, labelMap) ) - return false ; - if ( ! nodeIso(p1, p2, labelMap) ) - return false ; - if ( ! nodeIso(o1, o2, labelMap) ) - return false ; - - return true ; + public static boolean tripleIso(Triple t1, Triple t2, NodeIsomorphismMap labelMap) { + Node s1 = t1.getSubject(); + Node p1 = t1.getPredicate(); + Node o1 = t1.getObject(); + + Node s2 = t2.getSubject(); + Node p2 = t2.getPredicate(); + Node o2 = t2.getObject(); + + if ( !nodeIso(s1, s2, labelMap) ) + return false; + if ( !nodeIso(p1, p2, labelMap) ) + return false; + if ( !nodeIso(o1, o2, labelMap) ) + return false; + + return true; } - /* - * Are two quads isomorphic? - * The mapping policy {@link NodeIsomorphismMap} is mutated. + /** + * Are two quads isomorphic? The mapping policy {@link NodeIsomorphismMap} is + * mutated. */ - public static boolean quadIso(Quad t1, Quad t2, NodeIsomorphismMap labelMap) - { - Node g1 = t1.getGraph() ; - Node s1 = t1.getSubject() ; - Node p1 = t1.getPredicate() ; - Node o1 = t1.getObject() ; - - Node g2 = t2.getGraph() ; - Node s2 = t2.getSubject() ; - Node p2 = t2.getPredicate() ; - Node o2 = t2.getObject() ; - - if ( ! nodeIso(g1, g2, labelMap) ) - return false ; - if ( ! nodeIso(s1, s2, labelMap) ) - return false ; - if ( ! nodeIso(p1, p2, labelMap) ) - return false ; - if ( ! nodeIso(o1, o2, labelMap) ) - return false ; - - return true ; + public static boolean quadIso(Quad t1, Quad t2, NodeIsomorphismMap labelMap) { + Node g1 = t1.getGraph(); + Node s1 = t1.getSubject(); + Node p1 = t1.getPredicate(); + Node o1 = t1.getObject(); + + Node g2 = t2.getGraph(); + Node s2 = t2.getSubject(); + Node p2 = t2.getPredicate(); + Node o2 = t2.getObject(); + + if ( !nodeIso(g1, g2, labelMap) ) + return false; + if ( !nodeIso(s1, s2, labelMap) ) + return false; + if ( !nodeIso(p1, p2, labelMap) ) + return false; + if ( !nodeIso(o1, o2, labelMap) ) + return false; + + return true; } - /* - * Are two nodes isomorphic? - * The mapping policy {@link NodeIsomorphismMap} is mutated. + /** + * Are two nodes isomorphic? The mapping policy {@link NodeIsomorphismMap} is + * mutated. */ - public static boolean nodeIso(Node n1, Node n2, NodeIsomorphismMap isoMap) - { + public static boolean nodeIso(Node n1, Node n2, NodeIsomorphismMap isoMap) { if ( isoMap != null ) { if ( n1.isBlank() && n2.isBlank() ) - return isoMap.makeIsomorphic(n1, n2) ; + return isoMap.makeIsomorphic(n1, n2); if ( Var.isBlankNodeVar(n1) && Var.isBlankNodeVar(n2) ) return isoMap.makeIsomorphic(n1, n2) ; - } - return n1.equals(n2) ; - } - - /** Interface for choosing the pairs of node that can be map[ped for isomorphism. */ - public interface Mappable { - boolean isMappable(Node n); - boolean mappable(Node n1, Node n2); - } - - /** Blank nodes are mappable in {@link IsoAlg} */ - public static Iso.Mappable mappableBlankNodes = new Mappable() { - @Override public boolean isMappable(Node n) { return n.isBlank(); } - @Override public boolean mappable(Node n1, Node n2) { return n1.isBlank() && n2.isBlank(); } - }; - - /** Blank nodes and variables are mappable in {@link IsoAlg} */ - public static Iso.Mappable mappableVariables = new Mappable() { - @Override public boolean isMappable(Node n) { return n.isVariable(); } - @Override public boolean mappable(Node n1, Node n2) { return n1.isVariable() && n2.isVariable(); } - }; - - - /** Blank nodes and variables are mappable in {@link IsoAlg} */ - public static Iso.Mappable mappableBlankNodesVariables = new Mappable() { - @Override public boolean isMappable(Node n) { return n.isBlank()|| n.isVariable() ; } - @Override public boolean mappable(Node n1, Node n2) { - if ( n1.isBlank() && n2.isBlank() ) return true; - if ( n1.isVariable() && n2.isVariable() ) return true; - return false; + if ( n1.isTripleTerm() && n2.isTripleTerm() ) + return tripleIso(n1.getTriple(), n2.getTriple(), isoMap); + if ( n1.isNodeGraph() && n2.isNodeGraph() ) { + List list1 = n1.getGraph().find().toList(); + List list2 = n2.getGraph().find().toList(); + return isomorphicTriples(list1, list2, isoMap); + } } - }; + return n1.equals(n2); + } } - diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/IsoMatcher.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/IsoMatcher.java index 6230fd13124..6e3ba9581d6 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/util/IsoMatcher.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/IsoMatcher.java @@ -31,16 +31,19 @@ import org.apache.jena.graph.Triple ; import org.apache.jena.sparql.core.DatasetGraph ; import org.apache.jena.sparql.core.Quad ; +import org.apache.jena.sparql.util.iso.IsoAlgRows; +import org.apache.jena.sparql.util.iso.IsoAlgTuple; +import org.apache.jena.util.iterator.ExtendedIterator; /** * Simple isomorphism testing for on unordered collections. * This code is simple and slow. - * For graphs, the Graph isomorphism code in Jena is much better (better tested, better performance) * This code can work on any tuples of nodes. * * See {@link Iso} for isomorphism for ordered lists. * - * See {@link IsoAlg} for the isomorphism algorithm. + * See {@link IsoAlgTuple} for the isomorphism algorithm. + * See {@link IsoAlgRows} for the isomorphism algorithm for rowsets. */ public class IsoMatcher { @@ -64,20 +67,23 @@ public static boolean isomorphic(Collection> x1, Collection>} */ - /*package*/ static List> tuplesTriples(Iterator iter) { - return Iter.iter(iter).map(t->tuple(t.getSubject(), t.getPredicate(), t.getObject())).toList(); + private static List> tuplesQuads(Iterator iter) { + return Iter.iter(iter).map(q->tuple(q.getGraph(), q.getSubject(), q.getPredicate(), q.getObject())).toList(); } /** Helper - convert to {@code List>} */ - public static List> tuplesQuads(Iterator iter) { - return Iter.iter(iter).map(q->tuple(q.getGraph(), q.getSubject(), q.getPredicate(), q.getObject())).toList(); + private static List> tuplesTriples(ExtendedIterator iter) { + try { + return Iter.iter(iter).map(t->tuple(t.getSubject(), t.getPredicate(), t.getObject())).toList(); + } + finally { iter.close(); } } /** Collection of tuples isomorphism, with choice of when two nodes are "equal". - * See also {@link IsoAlg#isIsomorphic(Collection, Collection, org.apache.jena.sparql.util.Iso.Mappable, EqualityTest)} + * See also {@link IsoAlgTuple#isIsomorphic(Collection, Collection, org.apache.jena.sparql.util.Iso.Mappable, EqualityTest)} * for isomorphisms testing for more than just blank nodes. */ - public static boolean isomorphic(Collection> x1, Collection> x2, EqualityTest nodeTest) { - return IsoAlg.isIsomorphic(x1, x2, nodeTest); + private static boolean isomorphic(Collection> x1, Collection> x2, EqualityTest nodeTest) { + return IsoAlgTuple.isIsomorphic(x1, x2, nodeTest); } } diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/NodeIsomorphismMap.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/NodeIsomorphismMap.java index 7bc86d7645f..f80d3b3b2f7 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/util/NodeIsomorphismMap.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/NodeIsomorphismMap.java @@ -18,30 +18,35 @@ package org.apache.jena.sparql.util; -import java.util.HashMap ; -import java.util.Map ; +import java.util.HashMap; +import java.util.Map; -import org.apache.jena.graph.Node ; +import org.apache.jena.graph.Node; /** Map nodes to nodes. */ public class NodeIsomorphismMap { - private Map map = new HashMap<>() ; - + private Map map = new HashMap<>(); + public NodeIsomorphismMap() {} - - private Node get(Node key) { return map.get(key) ; } - private void put(Node key, Node value) { map.put(key, value) ; } - + + private Node get(Node key) { return map.get(key); } + private void put(Node key, Node value) { map.put(key, value); } + public boolean makeIsomorphic(Node n1, Node n2) { if ( n1.isBlank() && n2.isBlank() ) { - Node other = get(n1) ; + Node other = get(n1); if ( other == null ) { - put(n1, n2) ; - return true ; + put(n1, n2); + return true; } - return other.equals(n2) ; + return other.equals(n2); } - return n1.equals(n2) ; + return n1.equals(n2); + } + + @Override + public String toString() { + return "Iso["+map.toString()+"]"; } } diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/NodeToLabelMap.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/NodeToLabelMap.java index 52877633e70..ab75c73e079 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/util/NodeToLabelMap.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/NodeToLabelMap.java @@ -18,85 +18,55 @@ package org.apache.jena.sparql.util; -import java.util.HashMap ; -import java.util.Map ; +import java.util.HashMap; +import java.util.Map; -import org.apache.jena.graph.Node ; +import org.apache.jena.graph.Node; /** Map nodes to blank node representations. */ -public class NodeToLabelMap -{ +public class NodeToLabelMap { // Could abstract again as a node -> label cache + cache miss handler. - int bNodeCounter = 0 ; - Map bNodeStrings = new HashMap<>() ; - boolean bNodesAsFakeURIs = false ; - String prefixString = "b" ; + int bNodeCounter = 0; + Map bNodeStrings = new HashMap<>(); + boolean bNodesAsFakeURIs = false; + String prefixString = "b"; - public NodeToLabelMap() { this("b") ; } + public NodeToLabelMap() { + this("b"); + } - public NodeToLabelMap(String prefix) { this(prefix, false) ; } + public NodeToLabelMap(String prefix) { + this(prefix, false); + } - public NodeToLabelMap(String prefix, boolean bNodesAsFakeURIs) - { + public NodeToLabelMap(String prefix, boolean bNodesAsFakeURIs) { if ( prefix == null || prefix.equals("") ) - throw new IllegalArgumentException("Must provide a prefix") ; - this.prefixString = "_:"+prefix ; - this.bNodesAsFakeURIs = bNodesAsFakeURIs ; + throw new IllegalArgumentException("Must provide a prefix"); + this.prefixString = "_:" + prefix; + this.bNodesAsFakeURIs = bNodesAsFakeURIs; } // Null means not mapped - public String asString(Node n) - { - if ( ! n.isBlank() ) - return null ; - - return mapNode(n) ; + public String asString(Node n) { + if ( !n.isBlank() ) + return null; + return mapNode(n); } // synchronized because this may be used from a static via FmtUtils - protected synchronized String mapNode(Node n) - { - String s = bNodeStrings.get(n) ; + protected synchronized String mapNode(Node n) { + String s = bNodeStrings.get(n); if ( s != null ) - return s ; + return s; - s = genStringForNode(n) ; - bNodeStrings.put(n, s) ; - return s ; + s = genStringForNode(n); + bNodeStrings.put(n, s); + return s; } - protected String genStringForNode(Node n) - { + protected String genStringForNode(Node n) { if ( bNodesAsFakeURIs && n.isBlank() ) - return "<_:"+n.getBlankNodeLabel()+">" ; - - return prefixString+(bNodeCounter++) ; + return "<_:" + n.getBlankNodeLabel() + ">"; + return prefixString + (bNodeCounter++); } - -// /** -// * @return Returns the prefix. -// */ -// public String getPrefixString() -// { -// return prefixString ; -// } -// -// /** -// * @param prefix The prefix to set. -// */ -// public void setPrefixString(String prefix) -// { -// if ( prefix == null ) -// { -// Log.fatal(this,"Prefix string is null") ; -// throw new ARQInternalErrorException("Prefix string is null") ; -// } -// if ( prefix.equals("") ) -// { -// Log.fatal(this,"Prefix string is the empty string") ; -// throw new ARQInternalErrorException("Prefix string is the empty string") ; -// } -// -// this.prefixString = prefix ; -// } } diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/iso/BNodeIso.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/iso/BNodeIso.java new file mode 100644 index 00000000000..692c31142ad --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/iso/BNodeIso.java @@ -0,0 +1,87 @@ +/* + * 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.sparql.util.iso; + +import org.apache.jena.graph.Node; +import org.apache.jena.graph.Triple; +import org.apache.jena.sparql.util.EqualityTest; +import org.apache.jena.sparql.util.Iso; +import org.apache.jena.sparql.util.NodeIsomorphismMap; +import org.apache.jena.sparql.util.NodeUtils; + +public class BNodeIso implements EqualityTest +{ + /** Kind of matching to perform. */ + // BNODES => blank node isomorphism. + public enum Match { BNODES_TERM, BNODES_VALUE, EXACT_TERM, EXACT_VALUE } + + /** + * Create a fresh {@link EqualityTest} that provides blank node isomorphism and + * comparision by term. + */ + public static EqualityTest bnodeIsoByTerm() { + return new BNodeIso(NodeUtils.sameRdfTerm); + } + + /** + * Create a fresh {@link EqualityTest} that provides blank node isomorphism and + * comparision by term. + */ + public static EqualityTest bnodeIsoByValue() { + return new BNodeIso(NodeUtils.sameValue); + } + + private NodeIsomorphismMap mapping; + private EqualityTest literalTest; + + private BNodeIso(EqualityTest literalTest) { + this.mapping = new NodeIsomorphismMap(); + this.literalTest = literalTest; + } + + @Override + public boolean equal(Node n1, Node n2) { + if ( n1 == null && n2 == null ) + return true; + if ( n1 == null ) + return false; + if ( n2 == null ) + return false; + + if ( n1.isURI() && n2.isURI() ) + return n1.equals(n2); + + if ( n1.isLiteral() && n2.isLiteral() ) + return literalTest.equal(n1, n2); + + if ( n1.isBlank() && n2.isBlank() ) + return Iso.nodeIso(n1, n2, mapping); + + if ( n1.isVariable() && n2.isVariable() ) + return mapping.makeIsomorphic(n1, n2); + + if ( n1.isTripleTerm() && n2.isTripleTerm() ) { + Triple t1 = n1.getTriple(); + Triple t2 = n2.getTriple(); + return Iso.tripleIso(t1, t2, mapping); + } + + return false; + } +} \ No newline at end of file diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoAlgRows.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoAlgRows.java new file mode 100644 index 00000000000..220de7a008c --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoAlgRows.java @@ -0,0 +1,272 @@ +/* + * 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.sparql.util.iso; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +import org.apache.jena.atlas.io.IndentedWriter; +import org.apache.jena.atlas.iterator.Iter; +import org.apache.jena.atlas.lib.InternalErrorException; +import org.apache.jena.graph.Node; +import org.apache.jena.graph.Triple; +import org.apache.jena.sparql.core.Var; +import org.apache.jena.sparql.engine.binding.Binding; +import org.apache.jena.sparql.exec.RowSet; +import org.apache.jena.sparql.util.EqualityTest; +import org.apache.jena.sparql.util.NodeUtils; +import org.apache.jena.sparql.util.iso.IsoLib.Mappable; + +public class IsoAlgRows { + + private static final boolean DEBUG = false; + private static final IndentedWriter out = debugIndentedWriter(); + private static final IndentedWriter debugIndentedWriter() { + IndentedWriter iout = null; + if ( DEBUG ) { + iout = new IndentedWriter(System.out); + iout.setFlushOnNewline(true); + } + return iout; + } + + public static boolean isIsomorphic(RowSet rowset1, RowSet rowset2, BNodeIso.Match matching) { + Objects.requireNonNull(rowset1); + Objects.requireNonNull(rowset2); + if ( rowset1 == rowset2 ) + return true; + if ( ! IsoLib.compareHeader(rowset1, rowset2) ) + return false; + List rows1 = toList(rowset1); + List rows2 = toList(rowset2); + if ( rows1.size() != rows2.size() ) + return false; + + // Could divide into rows with exact matches (no blank nodes) and those with + // blank nodes. + + return matcher(rows1, rows2, matching); + } + + public static boolean isIsomorphic(List list1, List list2, BNodeIso.Match matching) { + if ( list1.size() != list2.size() ) + return false; + return matcher(list1, list2, matching); + } + + private static boolean matcher(List list1, List list2, BNodeIso.Match matching) { + Mappable mapping; + EqualityTest equalityTest; + switch(matching) { + case BNODES_TERM, EXACT_TERM -> equalityTest = NodeUtils.sameRdfTerm; + case BNODES_VALUE, EXACT_VALUE -> equalityTest = NodeUtils.sameValue; + default -> { throw new InternalErrorException("Unknown equality policy"); } + } + switch(matching) { + case EXACT_VALUE, EXACT_TERM -> mapping = IsoLib.mappableNoMap; + case BNODES_TERM, BNODES_VALUE -> mapping = IsoLib.mappableBlankNodes; + default -> { throw new InternalErrorException("Unknown matching policy"); } + } + + return matcherWorker(list1, 0, list2, IsoMapping.rootMapping, mapping, equalityTest); + } + + // Match rows in rows1, starting at idx1, against rows in rows2, starting at idx2 + private static boolean matcherWorker(List rows1, int idx1, List rows2, + IsoMapping mapping, IsoLib.Mappable mappable, EqualityTest equalityTest) { + if ( rows1.size() == 0 ) + return true; + + for ( int i = idx1 ; i < rows1.size() ; i++ ) { + Binding row1 = rows1.get(i); + if ( row1 == null ) + continue; + if ( DEBUG ) + out.println("-- Row1 = "+row1); + List possibilities = matcherOneRow(row1, rows2, mapping, mappable, equalityTest); + if ( DEBUG ) + out.println("Possibilities: "+possibilities); + + if ( possibilities.isEmpty() ) + return false; + + for ( Possibility poss : possibilities ) { + if ( DEBUG ) + out.println("Try: " + poss); + // Without this row1, and the possibility row can we map the rest? + int iRest = i+1; + if ( iRest >= rows1.size() ) { + // Last item + if ( DEBUG ) + out.println("Yes (zero left)"); + return true; + } + // One element of row2 removed. Not by position. + List rows2x = new ArrayList<>(rows2); + rows2x.remove(poss.row); + + if ( DEBUG ) + out.incIndent(); + + if ( matcherWorker(rows1, iRest, rows2x, poss.mapping, mappable, equalityTest) ) { + if ( DEBUG ) + out.decIndent(); + + if ( DEBUG ) + out.println("Yes"); + return true; + } + if ( DEBUG ) + out.decIndent(); + if ( DEBUG ) + out.println("No"); + } + // No possibility + return false; + } + // Maybe a bug in this code + return false; + } + + private static List matcherOneRow(Binding row1, List rows2, IsoMapping mapping, IsoLib.Mappable mappable, EqualityTest equalityTest) { + // find in rows2. + List possibilities = new ArrayList<>(); + for ( int j = 0 ; j < rows2.size() ; j++ ) { + Binding row2 = rows2.get(j); + if ( row2 == null ) + continue; + if ( DEBUG ) + out.printf("%-2d Row2 = %s\n", j, row2); + IsoMapping step = matchOne(row1, row2, mapping, mappable, equalityTest); + if ( step == null ) + continue; + Possibility poss = new Possibility(row2, step); + if ( DEBUG ) + out.println(poss.toString()); + // if row1 all concrete, drop row1 and row2 + possibilities.add(poss); + } + return possibilities; + } + + /** Can row1 be matched by row2? */ + private static IsoMapping matchOne(Binding row1, Binding row2, IsoMapping mapping, IsoLib.Mappable mappable, EqualityTest equalityTest) { +// Set vars1 = row1.varsMentioned(); +// Set vars2 = row2.varsMentioned(); +// if ( ! vars1.equals(vars2) ) +// return null; + + Iterator iter = row1.vars(); + IsoMapping mapping2 = mapping; + while(iter.hasNext()) { + Var v = iter.next(); + Node n1 = row1.get(v); + Node n2 = row2.get(v); + if ( n2 == null ) + return null; + mapping2 = matchTerms(n1, n2, mapping2, mappable, equalityTest); + if ( mapping2 == null ) + return null; + if ( DEBUG ) + out.println("Mapping: "+mapping2); + + } + return mapping2; + } + + /*package*/ static IsoMapping matchTermsTest(Node n1, Node n2, EqualityTest nodeTest) { + EqualityTest eqtest = BNodeIso.bnodeIsoByTerm(); + return matchTerms(n1, n2, IsoMapping.rootMapping, IsoLib.mappableBlankNodes, eqtest); + } + + static IsoMapping matchTerms(Node n1, Node n2, IsoMapping _mapping, IsoLib.Mappable mappable, EqualityTest nodeTest) { + if ( _mapping == null ) + return null; + if ( n1 == null || n2 == null ) + return null; + IsoMapping mapping = _mapping; + Node n1m = mapping.map(n1); + + if ( n1m != null ) { + // Already mapped + if ( DEBUG ) + out.printf("Existing: %s -> %s for %s\n", n1, n1m, n2); + if ( n1m.equals(n2) ) + // Exact equals after mapping t1 slot. + return mapping; + // No match. + return null; + } + + if ( n1.isTripleTerm() ) { + if ( n2.isTripleTerm() ) { + Triple t1 = n1.getTriple(); + Triple t2 = n2.getTriple(); + mapping = matchTerms(t1.getSubject(), t2.getSubject(), mapping, mappable, nodeTest); + if ( mapping == null ) + return null; + mapping = matchTerms(t1.getPredicate(), t2.getPredicate(), mapping, mappable, nodeTest); + if ( mapping == null ) + return null; + mapping = matchTerms(t1.getObject(), t2.getObject(), mapping, mappable, nodeTest); + if ( mapping == null ) + return null; + return mapping; + } + // n2 not a triple term. + return null; + } else if ( n2.isTripleTerm() ) { + // n1 not a triple term. + return null; + } + + // Map an atomic term (not triple term) + if ( mappable.mappable(n1, n2) ) { + if ( mapping.reverseMapped(n2) ) { + // Already a target. + // but not the same (else n1m != null) + return null; + } + // Add mapping. + mapping = new IsoMapping(mapping, n1, n2); + return mapping; + } + + if ( !nodeTest.equal(n1, n2) ) + // No isomorphism. + return null; + + return mapping; + } + + + static private List toList(RowSet rs) { + return Iter.iter(rs).toList(); + } + + private record Possibility(Binding row, IsoMapping mapping) { + @Override + public String toString() { + return String.format("Poss|%s %s|", IsoLib.str(row), mapping); + } + } +} + diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/IsoAlg.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoAlgTuple.java similarity index 63% rename from jena-arq/src/main/java/org/apache/jena/sparql/util/IsoAlg.java rename to jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoAlgTuple.java index 3ce8de4514a..9040c3218c0 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/util/IsoAlg.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoAlgTuple.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package org.apache.jena.sparql.util; +package org.apache.jena.sparql.util.iso; import java.util.ArrayList; import java.util.Collection; @@ -29,7 +29,9 @@ import org.apache.jena.atlas.lib.tuple.TupleFactory; import org.apache.jena.graph.Node; import org.apache.jena.graph.Triple; -import org.apache.jena.sparql.util.Iso.Mappable; +import org.apache.jena.sparql.util.EqualityTest; +import org.apache.jena.sparql.util.Iso; +import org.apache.jena.sparql.util.NodeUtils; /** * Simple isomorphism testing for collections of tuples of nodes. This can be used @@ -37,75 +39,65 @@ * better (better tested, better performance) for graph isomorphism. This code is * simple, easier to understand, and works on collections of tuples, not just graphs. */ -public class IsoAlg { - - /** Record the mapping of a node. This is a one-way linked list. */ - public static class Mapping { - final Node node1; - final Node node2; - final Mapping parent; - - public static final Mapping rootMapping = new Mapping(null, null, null); - - public Mapping(Mapping parent, Node node1, Node node2) { - super(); - this.parent = parent; - this.node1 = node1; - this.node2 = node2; - } - - public boolean mapped(Node node) { - return map(node) != null; - } - - public Node map(Node node) { - Mapping mapping = this; - while (mapping != rootMapping) { - if ( mapping.node1.equals(node) ) - return mapping.node2; - mapping = mapping.parent; - } - return null; - } - - public boolean reverseMapped(Node node) { - return reverseMap(node) != null; - } - - public Node reverseMap(Node node) { - Mapping mapping = this; - while (mapping != rootMapping) { - if ( mapping.node2.equals(node) ) - return mapping.node1; - mapping = mapping.parent; - } - return null; - } - - - @Override - public String toString() { - StringBuilder sbuff = new StringBuilder(); - Mapping mapping = this; - while (mapping != rootMapping) { - sbuff.append("{" + mapping.node1 + " => " + mapping.node2 + "}"); - mapping = mapping.parent; - } - sbuff.append("{}"); - return sbuff.toString(); - } - } - - static class Possibility { - final Tuple tuple; - final Mapping mapping; - - public Possibility(Tuple tuple, Mapping mapping) { - super(); - this.tuple = tuple; - this.mapping = mapping; - } - +public class IsoAlgTuple { + +// /** Record the IsoMapping of a node. This is a one-way linked list. */ +// private static class IsoMapping { +// final Node node1; +// final Node node2; +// final IsoMapping parent; +// +// static final IsoMapping rootIsoMapping = new Mapping(null, null, null); +// +// Mapping(IsoMapping parent, Node node1, Node node2) { +// super(); +// this.parent = parent; +// this.node1 = node1; +// this.node2 = node2; +// } +// +// boolean mapped(Node node) { +// return map(node) != null; +// } +// +// Node map(Node node) { +// IsoMapping IsoMapping = this; +// while (IsoMapping != rootMapping) { +// if ( mapping.node1.equals(node) ) +// return mapping.node2; +// IsoMapping = mapping.parent; +// } +// return null; +// } +// +// boolean reverseMapped(Node node) { +// return reverseMap(node) != null; +// } +// +// Node reverseMap(Node node) { +// IsoMapping IsoMapping = this; +// while (IsoMapping != rootMapping) { +// if ( mapping.node2.equals(node) ) +// return mapping.node1; +// IsoMapping = mapping.parent; +// } +// return null; +// } +// +// @Override +// public String toString() { +// StringBuilder sbuff = new StringBuilder(); +// IsoMapping IsoMapping = this; +// while (IsoMapping != rootMapping) { +// sbuff.append("{" + mapping.node1 + " => " + mapping.node2 + "}"); +// IsoMapping = mapping.parent; +// } +// sbuff.append("{}"); +// return sbuff.toString(); +// } +// } + + private record Possibility(Tuple tuple, IsoMapping mapping) { @Override public String toString() { return String.format("Poss|%s %s|", tuple, mapping); @@ -121,51 +113,55 @@ public String toString() { * or {@link NodeUtils#sameRdfTerm} (Node.equals, with lang tag insensitive testing). */ public static boolean isIsomorphic(Collection> x1, Collection> x2, EqualityTest nodeTest) { - return isIsomorphic(x1, x2, Iso.mappableBlankNodes, nodeTest); + return isIsomorphic(x1, x2, IsoLib.mappableBlankNodes, nodeTest); } /** - * Isomorphism test based on a class of mappable elements (e.g. blank nodes {@linkplain Iso#mappableBlankNodes}, + * Isomorphism test based on a class of IsoLib.Mappable elements (e.g. blank nodes {@linkplain Iso#mappableBlankNodes}, * or blank nodes and variables {@linkplain Iso#mappableBlankNodesVariables}). * Two nodes considered "equal" by an equality test such as * {@link NodeUtils#sameValue} (SPARQL value testing), * {@link NodeUtils#sameNode} (Node.equals), * or {@link NodeUtils#sameRdfTerm} (Node.equals, with lang tag insensitive testing). */ - public static boolean isIsomorphic(Collection> x1, Collection> x2, Iso.Mappable mappable, EqualityTest nodeTest) { - return matcher(x1, x2, Mapping.rootMapping, mappable, nodeTest); + /*package*/ static boolean isIsomorphic(Collection> x1, Collection> x2, IsoLib.Mappable mappable, EqualityTest nodeTest) { + if ( x1.size() != x2.size() ) + return false; + return matcher(x1, x2, IsoMapping.rootMapping, mappable, nodeTest); } /** - * Isomorphism test based on a class of mappable elements (e.g. blank nodes {@linkplain Iso#mappableBlankNodes}, + * Isomorphism test based on a class of IsoLib.Mappable elements (e.g. blank nodes {@linkplain Iso#mappableBlankNodes}, * or blank nodes and variables {@linkplain Iso#mappableBlankNodesVariables}). * Two nodes considered "equal" by an equality test such as * {@link NodeUtils#sameValue} (SPARQL value testing), * {@link NodeUtils#sameNode} (Node.equals), * or {@link NodeUtils#sameRdfTerm} (Node.equals, with lang tag insensitive testing). */ - public static Mapping isIsomorphic(Tuple tuple1, Tuple tuple2, Mapping mapping, Mappable mappable, EqualityTest nodeTest) { - return gen(tuple1, tuple2, mapping, mappable, nodeTest); + private static IsoMapping isIsomorphic(Tuple tuple1, Tuple tuple2, IsoMapping mapping, IsoLib.Mappable mappable, EqualityTest nodeTest) { + return matchTuples(tuple1, tuple2, mapping, mappable, nodeTest); } // Debug. private static final boolean DEBUG = false; - private static final IndentedWriter out = new IndentedWriter(System.out); - static { - out.setFlushOnNewline(true); + private static final IndentedWriter out = debugIndentedWriter(); + private static final IndentedWriter debugIndentedWriter() { + IndentedWriter iout = null; + if ( DEBUG ) { + iout = new IndentedWriter(System.out); + iout.setFlushOnNewline(true); + } + return iout; } - private static boolean matcher(Collection> tuples1, Collection> tuples2, Mapping mapping, - Iso.Mappable mappable, EqualityTest nodeTest) { + private static boolean matcher(Collection> tuples1, Collection> tuples2, IsoMapping mapping, + IsoLib.Mappable mappable, EqualityTest nodeTest) { if ( DEBUG ) { out.println("match: "); out.println(" 1: " + tuples1); out.println(" 2: " + tuples2); out.println(" M: " + mapping); } - if ( tuples1.size() != tuples2.size() ) - return false; - // Process the inputs : tuples of all non-mappable terms can be processed here (Node.equals) // Loop on tuples1: // if not mappable, remove from tuples2. @@ -176,6 +172,7 @@ private static boolean matcher(Collection> tuples1, Collection> tuples1$ = new ArrayList<>(); // Step one - copy non-mappable tuples or exit now. for ( Tuple t1 : tuples1 ) { @@ -187,7 +184,7 @@ private static boolean matcher(Collection> tuples1, Collection> tuples1, Collection causes = matcher(t1, tuples2, mapping, mappable, nodeTest); - if ( DEBUG ) + if ( DEBUG ) { out.println(" Possibilities: Tuple" + t1 + " :: " + causes); - - out.incIndent(); + out.incIndent(); + } try { // Try each possible tuple-tuple matching until one succeeds all the // way. @@ -218,9 +215,9 @@ private static boolean matcher(Collection> tuples1, Collection t2 Tuple t2 = c.tuple; tuples2.remove(t2); - // Try without t1 and t2, using the mapping of this cause. - if ( tuples1.isEmpty() && tuples2.isEmpty() ) // They are the - // same size. + // Try without t1 and t2, using the IsoMapping of this cause. + if ( tuples1.isEmpty() && tuples2.isEmpty() ) + // They are the same size. return true; // Recurse if ( matcher(tuples1, tuples2, c.mapping, mappable, nodeTest) ) { @@ -235,7 +232,7 @@ private static boolean matcher(Collection> tuples1, Collection tuple) { } /** Return all possible tuple-tuple matches from tuple t1 to tuples in x2 */ - private static List matcher(Tuple t1, Collection> g2, Mapping mapping, Iso.Mappable mappable, - EqualityTest nodeTest) { + private static List matcher(Tuple t1, Collection> g2, IsoMapping mapping, IsoLib.Mappable mappable, EqualityTest nodeTest) { List matches = new ArrayList<>(); for ( Tuple t2 : g2 ) { - Mapping step = gen(t1, t2, mapping, mappable, nodeTest); + IsoMapping step = matchTuples(t1, t2, mapping, mappable, nodeTest); if ( step != null ) { Possibility c = new Possibility(t2, step); matches.add(c); @@ -272,19 +268,19 @@ private static List matcher(Tuple t1, Collection> } /** - * Find a mapping between the tuples, given a start mapping. - * Return a mapping or null for "no match". + * Find a IsoMapping between the tuples, given a start mapping. + * Return a IsoMapping or null for "no match". */ - private static Mapping gen(Tuple t1, Tuple t2, Mapping _mapping, Iso.Mappable mappable, EqualityTest nodeTest) { + private static IsoMapping matchTuples(Tuple t1, Tuple t2, IsoMapping _mapping, IsoLib.Mappable mappable, EqualityTest nodeTest) { if ( t1.len() != t2.len() ) return null; - Mapping mapping = _mapping; + IsoMapping mapping = _mapping; for ( int i = 0 ; i < t1.len() ; i++ ) { Node n1 = t1.get(i); Node n2 = t2.get(i); - Mapping mapping2 = gen(n1, n2, mapping, mappable, nodeTest); + IsoMapping mapping2 = matchTerms(n1, n2, mapping, mappable, nodeTest); if ( mapping2 == null ) return null; mapping = mapping2; @@ -297,15 +293,14 @@ private static Mapping gen(Tuple t1, Tuple t2, Mapping _mapping, Iso triple.getPredicate(), triple.getObject()); - - static Mapping gen(Node n1, Node n2, Mapping _mapping, Iso.Mappable mappable, EqualityTest nodeTest) { - Mapping mapping = _mapping; + static IsoMapping matchTerms(Node n1, Node n2, IsoMapping _mapping, IsoLib.Mappable mappable, EqualityTest nodeTest) { + IsoMapping mapping = _mapping; Node n1m = mapping.map(n1); if ( n1m != null ) { // Already mapped if ( n1m.equals(n2) ) - // Exact equals after mapping t1 slot. + // Exact equals after IsoMapping n1. return mapping; // No match. return null; @@ -317,8 +312,7 @@ static Mapping gen(Node n1, Node n2, Mapping _mapping, Iso.Mappable mappable, Eq Triple t2 = n2.getTriple(); Tuple tuple1 = tripleToTuple.apply(t1); Tuple tuple2 = tripleToTuple.apply(t2); - // Whether to records the triple term mapping. - return gen(tuple1, tuple2, mapping, mappable, nodeTest); + return matchTuples(tuple1, tuple2, mapping, mappable, nodeTest); } } else if ( n2.isTripleTerm() ) { return null; @@ -333,7 +327,7 @@ static Mapping gen(Node n1, Node n2, Mapping _mapping, Iso.Mappable mappable, Eq } // **** If n2 not already mapped. - mapping = new Mapping(mapping, n1, n2); + mapping = new IsoMapping(mapping, n1, n2); return mapping; } diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoLib.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoLib.java new file mode 100644 index 00000000000..f0506dd11f7 --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoLib.java @@ -0,0 +1,125 @@ +/* + * 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.sparql.util.iso; + +import java.util.Iterator; +import java.util.Set; + +import org.apache.jena.graph.Node; +import org.apache.jena.riot.out.NodeFmtLib; +import org.apache.jena.sparql.core.Var; +import org.apache.jena.sparql.engine.binding.Binding; +import org.apache.jena.sparql.exec.RowSet; +import org.apache.jena.sparql.exec.RowSetRewindable; +import org.apache.jena.sparql.util.EqualityTest; + +/** + * Shared stuff. Where does this go? + */ +class IsoLib { + static final boolean DEBUG = false; + + /** + * Interface for choosing the pairs of node that can be mapped for isomorphism. + */ + @FunctionalInterface + interface Mappable { + boolean mappable(Node n1, Node n2); + } + + /** Blank nodes are mappable in {@link IsoAlgTuple} */ + static Mappable mappableBlankNodes = (Node n1, Node n2) -> n1.isBlank() && n2.isBlank(); + + static Mappable mappableVariables = (Node n1, Node n2) -> n1.isVariable() && n2.isVariable(); + + static Mappable mappableBlankNodesVariables = (Node n1, Node n2) -> { + if ( n1.isBlank() && n2.isBlank() ) return true; + if ( n1.isVariable() && n2.isVariable() ) return true; + return false; + }; + + /** Exact match only (a separate test), same term, blank nodes have same label. */ + static Mappable mappableNoMap = (Node n1, Node n2) -> false; + + static boolean compareHeader(RowSet rs1, RowSet rs2) { + if ( rs1 == null && rs2 == null ) + return true; + if ( rs1 == null ) + return false; + if ( rs2 == null ) + return false; + Set names1 = Set.copyOf(rs1.getResultVars()); + Set names2 = Set.copyOf(rs2.getResultVars()); + return names1.equals(names2); + } + + static RowSetRewindable print(RowSet rs) { + RowSetRewindable rsw = rs.rewindable(); + rsw.forEach(binding->{ + String x = str(binding); + System.out.print(" "); + System.out.print(x); + System.out.println(); + }); + rsw.reset(); + return rsw; + } + + // String, with blank node ids, not "_:bN" + static String str(Binding binding) { + StringBuffer sbuff = new StringBuffer(); + binding.forEach((var, node)-> { + String tmp = NodeFmtLib.strNT(node); + sbuff.append("( ?" + var.getVarName() + " = " + tmp + " )"); + + }); + return sbuff.toString(); + } + + + /** Compare two bindings, use the node equality test provided */ + static boolean equal(Binding bind1, Binding bind2, EqualityTest test) { + if ( bind1 == bind2 ) + return true; + if ( bind1.size() != bind2.size() ) + return false; + // They are the same size so containment is enough. + if ( ! containedIn(bind1, bind2, test) ) + return false; + return true; + } + + // Is bind1 contained in bind2? For every (var,value) in bind1, is it in bind2? + // Maybe more in bind2. + private static boolean containedIn(Binding bind1, Binding bind2, EqualityTest test) { + Iterator iter1 = bind1.vars(); + while(iter1.hasNext()) { + Var v = iter1.next(); + Node n1 = bind1.get(v); + Node n2 = bind2.get(v); + if ( n2 == null ) + // v bound in bind1 and not in bind2. + return false; + if ( ! test.equal(n1, n2) ) + return false; + } + return true; + } + +} \ No newline at end of file diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoMapping.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoMapping.java new file mode 100644 index 00000000000..263db14b330 --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/iso/IsoMapping.java @@ -0,0 +1,67 @@ +/* + * 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.sparql.util.iso; + +import org.apache.jena.graph.Node; + +/** Record the mapping of a node. This is a one-way linked list. */ +/*package*/ record IsoMapping(IsoMapping parent, Node node1, Node node2) { + + static final IsoMapping rootMapping = new IsoMapping(null, null, null); + + boolean mapped(Node node) { + return map(node) != null; + } + + Node map(Node node) { + IsoMapping mapping = this; + while (mapping != rootMapping) { + if ( mapping.node1.equals(node) ) + return mapping.node2; + mapping = mapping.parent; + } + return null; + } + + boolean reverseMapped(Node node) { + return reverseMap(node) != null; + } + + Node reverseMap(Node node) { + IsoMapping mapping = this; + while (mapping != rootMapping) { + if ( mapping.node2.equals(node) ) + return mapping.node1; + mapping = mapping.parent; + } + return null; + } + + @Override + public String toString() { + StringBuilder sbuff = new StringBuilder(); + IsoMapping mapping = this; + while (mapping != rootMapping) { + sbuff.append("{" + mapping.node1 + " => " + mapping.node2 + "}"); + mapping = mapping.parent; + } + sbuff.append("{}"); + return sbuff.toString(); + } +} \ No newline at end of file diff --git a/jena-arq/src/test/java/org/apache/jena/arq/junit/sparql/tests/QueryEvalTest.java b/jena-arq/src/test/java/org/apache/jena/arq/junit/sparql/tests/QueryEvalTest.java index ce1b51a95fe..00d3377c526 100644 --- a/jena-arq/src/test/java/org/apache/jena/arq/junit/sparql/tests/QueryEvalTest.java +++ b/jena-arq/src/test/java/org/apache/jena/arq/junit/sparql/tests/QueryEvalTest.java @@ -50,7 +50,7 @@ import org.apache.jena.sparql.engine.iterator.QueryIterPlainWrapper; import org.apache.jena.sparql.expr.nodevalue.NodeFunctions; import org.apache.jena.sparql.junit.QueryTestException; -import org.apache.jena.sparql.resultset.ResultSetCompare; +import org.apache.jena.sparql.resultset.ResultsCompare; import org.apache.jena.sparql.resultset.SPARQLResult; import org.apache.jena.sparql.util.IsoMatcher; import org.apache.jena.sparql.vocabulary.ResultSetGraphVocab; @@ -211,7 +211,7 @@ private void runTestSelect(Query query, QueryExecution qe) { if ( results == null ) return; - // Assumes resultSetCompare can cope with full isomorphism possibilities. + // Assumes ResultsCompare can cope with full isomorphism possibilities. ResultSetRewindable resultsExpected; if ( results.isResultSet() ) resultsExpected = ResultSetFactory.makeRewindable(results.getResultSet()); @@ -301,14 +301,14 @@ private static ResultSetRewindable unique(ResultSetRewindable results) { private static boolean resultSetEquivalent(Query query, ResultSetRewindable resultsExpected, ResultSetRewindable resultsActual) { if ( compareResultSetsByValue ) { if ( query.isOrdered() ) - return ResultSetCompare.equalsByValueAndOrder(resultsExpected, resultsActual); + return ResultsCompare.equalsByValueAndOrder(resultsExpected, resultsActual); else - return ResultSetCompare.equalsByValue(resultsExpected, resultsActual); + return ResultsCompare.equalsByValue(resultsExpected, resultsActual); } else { if ( query.isOrdered() ) - return ResultSetCompare.equalsByTermAndOrder(resultsExpected, resultsActual); + return ResultsCompare.equalsByTermAndOrder(resultsExpected, resultsActual); else - return ResultSetCompare.equalsByTerm(resultsExpected, resultsActual); + return ResultsCompare.equalsByTerm(resultsExpected, resultsActual); } } diff --git a/jena-arq/src/test/java/org/apache/jena/atlas/data/DataBagExaminer.java b/jena-arq/src/test/java/org/apache/jena/atlas/data/DataBagExaminer.java index 2c2c4bac16e..2a3673b967d 100644 --- a/jena-arq/src/test/java/org/apache/jena/atlas/data/DataBagExaminer.java +++ b/jena-arq/src/test/java/org/apache/jena/atlas/data/DataBagExaminer.java @@ -18,20 +18,17 @@ package org.apache.jena.atlas.data; -import java.io.File ; +import java.io.File; /** - * This class exists so that we can examine the internals of a DataBag during testing (which we can do here since it is in the same package). + * This class exists so that we can examine the internals of a DataBag during testing + * (which we can do here since it is in the same package). */ -public class DataBagExaminer -{ - public static int countTemporaryFiles(AbstractDataBag bag) - { +public class DataBagExaminer { + public static int countTemporaryFiles(AbstractDataBag bag) { int count = 0; - for (File tempFile : bag.getSpillFiles()) - { - if (tempFile.exists()) - { + for ( File tempFile : bag.getSpillFiles() ) { + if ( tempFile.exists() ) { count++; } } diff --git a/jena-arq/src/test/java/org/apache/jena/atlas/data/TestDistinctDataBag.java b/jena-arq/src/test/java/org/apache/jena/atlas/data/TestDistinctDataBag.java index 734b96d1718..a75494a3e36 100644 --- a/jena-arq/src/test/java/org/apache/jena/atlas/data/TestDistinctDataBag.java +++ b/jena-arq/src/test/java/org/apache/jena/atlas/data/TestDistinctDataBag.java @@ -24,19 +24,22 @@ import java.io.File ; import java.util.*; +import org.junit.Test ; + import org.apache.jena.atlas.iterator.Iter ; import org.apache.jena.datatypes.xsd.XSDDatatype ; import org.apache.jena.graph.NodeFactory ; import org.apache.jena.query.SortCondition ; import org.apache.jena.sparql.core.Var ; -import org.apache.jena.sparql.engine.binding.*; -import org.apache.jena.sparql.resultset.ResultSetCompare ; +import org.apache.jena.sparql.engine.binding.Binding; +import org.apache.jena.sparql.engine.binding.BindingBuilder; +import org.apache.jena.sparql.engine.binding.BindingComparator; +import org.apache.jena.sparql.engine.binding.BindingFactory; +import org.apache.jena.sparql.resultset.ResultsCompare; import org.apache.jena.sparql.sse.Item ; import org.apache.jena.sparql.sse.SSE ; import org.apache.jena.sparql.sse.builders.BuilderBinding ; import org.apache.jena.sparql.system.SerializationFactoryFinder; -import org.apache.jena.sparql.util.NodeUtils ; -import org.junit.Test ; public class TestDistinctDataBag { @@ -51,8 +54,7 @@ public class TestDistinctDataBag static Binding bb1 = build("(?a _:XYZ) (?b 1)"); static Binding x10 = build("(?x )") ; - @Test public void testDistinct() - { + @Test public void testDistinct() { List undistinct = new ArrayList<>(); undistinct.add(b12); undistinct.add(b19); @@ -71,55 +73,44 @@ public class TestDistinctDataBag new ThresholdPolicyCount(2), SerializationFactoryFinder.bindingSerializationFactory(), new BindingComparator(new ArrayList())); - try - { + try { db.addAll(undistinct); Iterator iter = db.iterator(); - while (iter.hasNext()) - { + while (iter.hasNext()) { distinct.add(iter.next()); } Iter.close(iter); - } - finally - { + } finally { db.close(); } assertEquals(control.size(), distinct.size()); - assertTrue(ResultSetCompare.equalsByTest(control, distinct, NodeUtils.sameNode)); + assertTrue(ResultsCompare.equalsExact(control, distinct)); } - @Test public void testTemporaryFilesAreCleanedUpAfterCompletion() - { + @Test + public void testTemporaryFilesAreCleanedUpAfterCompletion() { List undistinct = new ArrayList<>(); random = new Random(); - Var[] vars = new Var[]{ - Var.alloc("1"), Var.alloc("2"), Var.alloc("3"), - Var.alloc("4"), Var.alloc("5"), Var.alloc("6"), - Var.alloc("7"), Var.alloc("8"), Var.alloc("9"), Var.alloc("0") - }; - for(int i = 0; i < 500; i++){ + Var[] vars = new Var[]{Var.alloc("1"), Var.alloc("2"), Var.alloc("3"), Var.alloc("4"), Var.alloc("5"), Var.alloc("6"), + Var.alloc("7"), Var.alloc("8"), Var.alloc("9"), Var.alloc("0")}; + for ( int i = 0 ; i < 500 ; i++ ) { undistinct.add(randomBinding(vars)); } - DistinctDataBag db = new DistinctDataBag<>( - new ThresholdPolicyCount(10), - SerializationFactoryFinder.bindingSerializationFactory(), - new BindingComparator(new ArrayList())); + DistinctDataBag db = new DistinctDataBag<>(new ThresholdPolicyCount(10), + SerializationFactoryFinder.bindingSerializationFactory(), + new BindingComparator(new ArrayList())); List spillFiles = new ArrayList<>(); - try - { + try { db.addAll(undistinct); spillFiles.addAll(db.getSpillFiles()); int count = 0; - for (File file : spillFiles) - { - if (file.exists()) - { + for ( File file : spillFiles ) { + if ( file.exists() ) { count++; } } @@ -127,36 +118,29 @@ public class TestDistinctDataBag assertEquals(49, count); Iterator iter = db.iterator(); - while (iter.hasNext()) - { + while (iter.hasNext()) { iter.next(); } Iter.close(iter); - } - finally - { + } finally { db.close(); } int count = 0; - for (File file : spillFiles) - { - if (file.exists()) - { + for ( File file : spillFiles ) { + if ( file.exists() ) { count++; } } assertEquals(0, count); } - private static Binding build(String string) - { - Item item = SSE.parse("(binding "+string+")") ; - return BuilderBinding.build(item) ; + private static Binding build(String string) { + Item item = SSE.parse("(binding " + string + ")"); + return BuilderBinding.build(item); } - private Binding randomBinding(Var[] vars) - { + private Binding randomBinding(Var[] vars) { BindingBuilder builder = Binding.builder(); builder.add(vars[0], NodeFactory.createBlankNode()); builder.add(vars[1], NodeFactory.createURI(randomURI())); @@ -171,15 +155,13 @@ private Binding randomBinding(Var[] vars) return builder.build(); } - public String randomURI() - { + public String randomURI() { return String.format("http://%s.example.com/%s", randomString(10), randomString(10)); } - public String randomString(int length) - { + public String randomString(int length) { StringBuilder builder = new StringBuilder(); - for(int i = 0; i < length; i++){ + for ( int i = 0 ; i < length ; i++ ) { builder.append(LETTERS.charAt(random.nextInt(LETTERS.length()))); } return builder.toString(); @@ -215,6 +197,6 @@ public void testOptionalVariables() { } assertEquals(control.size(), distinct.size()); - assertTrue(ResultSetCompare.equalsByTest(control, distinct, NodeUtils.sameNode)); + assertTrue(ResultsCompare.equalsExact(control, distinct)); } } diff --git a/jena-arq/src/test/java/org/apache/jena/atlas/data/TestDistinctDataNet.java b/jena-arq/src/test/java/org/apache/jena/atlas/data/TestDistinctDataNet.java index a84610195d6..09c267935f0 100644 --- a/jena-arq/src/test/java/org/apache/jena/atlas/data/TestDistinctDataNet.java +++ b/jena-arq/src/test/java/org/apache/jena/atlas/data/TestDistinctDataNet.java @@ -24,6 +24,8 @@ import java.io.File ; import java.util.*; +import org.junit.Test ; + import org.apache.jena.atlas.iterator.Iter ; import org.apache.jena.datatypes.xsd.XSDDatatype ; import org.apache.jena.graph.NodeFactory ; @@ -32,13 +34,11 @@ import org.apache.jena.sparql.engine.binding.Binding ; import org.apache.jena.sparql.engine.binding.BindingBuilder; import org.apache.jena.sparql.engine.binding.BindingComparator ; -import org.apache.jena.sparql.resultset.ResultSetCompare ; +import org.apache.jena.sparql.resultset.ResultsCompare; import org.apache.jena.sparql.sse.Item ; import org.apache.jena.sparql.sse.SSE ; import org.apache.jena.sparql.sse.builders.BuilderBinding ; import org.apache.jena.sparql.system.SerializationFactoryFinder; -import org.apache.jena.sparql.util.NodeUtils ; -import org.junit.Test ; public class TestDistinctDataNet { @@ -54,8 +54,7 @@ public class TestDistinctDataNet static Binding x10 = build("(?x )") ; @Test - public void testDistinct() - { + public void testDistinct() { List undistinct = new ArrayList<>(); undistinct.add(b12); undistinct.add(b19); @@ -74,29 +73,24 @@ public void testDistinct() new ThresholdPolicyCount(2), SerializationFactoryFinder.bindingSerializationFactory(), new BindingComparator(new ArrayList())); - try - { + try { db.addAll(undistinct); Iterator iter = db.iterator(); - while (iter.hasNext()) - { + while (iter.hasNext()) { distinct.add(iter.next()); } Iter.close(iter); - } - finally - { + } finally { db.close(); } assertEquals(control.size(), distinct.size()); - assertTrue(ResultSetCompare.equalsByTest(control, distinct, NodeUtils.sameNode)); + assertTrue(ResultsCompare.equalsExact(control, distinct)); } @Test - public void testDistinct2() - { + public void testDistinct2() { List undistinct = new ArrayList<>(); undistinct.add(b12); undistinct.add(b19); @@ -110,67 +104,51 @@ public void testDistinct2() List control = Iter.toList(Iter.distinct(undistinct.iterator())); List distinct = new ArrayList<>(); - - DistinctDataNet db = new DistinctDataNet<>( - new ThresholdPolicyCount(2), - SerializationFactoryFinder.bindingSerializationFactory(), - new BindingComparator(new ArrayList())); - try - { - for (Binding b : undistinct) - { - if (db.netAdd(b)) - { + DistinctDataNet db = new DistinctDataNet<>(new ThresholdPolicyCount(2), + SerializationFactoryFinder.bindingSerializationFactory(), + new BindingComparator(new ArrayList())); + try { + for ( Binding b : undistinct ) { + if ( db.netAdd(b) ) { distinct.add(b); } } Iterator iter = db.netIterator(); - while (iter.hasNext()) - { + while (iter.hasNext()) { distinct.add(iter.next()); } Iter.close(iter); - } - finally - { + } finally { db.close(); } assertEquals(control.size(), distinct.size()); - assertTrue(ResultSetCompare.equalsByTest(control, distinct, NodeUtils.sameNode)); + assertTrue(ResultsCompare.equalsExact(control, distinct)); } @Test - public void testTemporaryFilesAreCleanedUpAfterCompletion() - { + public void testTemporaryFilesAreCleanedUpAfterCompletion() { List undistinct = new ArrayList<>(); random = new Random(); - Var[] vars = new Var[]{ - Var.alloc("1"), Var.alloc("2"), Var.alloc("3"), - Var.alloc("4"), Var.alloc("5"), Var.alloc("6"), - Var.alloc("7"), Var.alloc("8"), Var.alloc("9"), Var.alloc("0") - }; - for(int i = 0; i < 500; i++){ + Var[] vars = new Var[]{Var.alloc("1"), Var.alloc("2"), Var.alloc("3"), Var.alloc("4"), Var.alloc("5"), Var.alloc("6"), + Var.alloc("7"), Var.alloc("8"), Var.alloc("9"), Var.alloc("0")}; + for ( int i = 0 ; i < 500 ; i++ ) { undistinct.add(randomBinding(vars)); } - DistinctDataNet db = new DistinctDataNet<>( - new ThresholdPolicyCount(10), - SerializationFactoryFinder.bindingSerializationFactory(), - new BindingComparator(new ArrayList())); + DistinctDataNet db = new DistinctDataNet<>(new ThresholdPolicyCount(10), + SerializationFactoryFinder.bindingSerializationFactory(), + new BindingComparator(new ArrayList())); List spillFiles = new ArrayList<>(); - try - { + try { db.addAll(undistinct); spillFiles.addAll(db.getSpillFiles()); int count = 0; - for (File file : spillFiles) - { - if (file.exists()) - { + for ( File file : spillFiles ) { + if ( file.exists() ) { count++; } } @@ -178,55 +156,42 @@ public void testTemporaryFilesAreCleanedUpAfterCompletion() assertEquals(49, count); Iterator iter = db.iterator(); - while (iter.hasNext()) - { + while (iter.hasNext()) { iter.next(); } Iter.close(iter); - } - finally - { + } finally { db.close(); } int count = 0; - for (File file : spillFiles) - { - if (file.exists()) - { + for ( File file : spillFiles ) { + if ( file.exists() ) { count++; } } assertEquals(0, count); } - private void testDiff(String first, String second, String expected) - { - DistinctDataNet.SortedDiffIterator.create( - Arrays.asList(first.split(" ")).iterator(), - Arrays.asList(second.split(" ")).iterator()); + private void testDiff(String first, String second, String expected) { + DistinctDataNet.SortedDiffIterator.create(Arrays.asList(first.split(" ")).iterator(), Arrays.asList(second.split(" ")).iterator()); } - private void testDiff(String[] first, String[] second, String expected) - { - DistinctDataNet.SortedDiffIterator sdi = DistinctDataNet.SortedDiffIterator.create( - Arrays.asList(first).iterator(), - Arrays.asList(second).iterator()); + private void testDiff(String[] first, String[] second, String expected) { + DistinctDataNet.SortedDiffIterator sdi = DistinctDataNet.SortedDiffIterator.create(Arrays.asList(first).iterator(), + Arrays.asList(second).iterator()); StringBuilder sb = new StringBuilder(); boolean firstTime = true; - while (sdi.hasNext()) - { - if (!firstTime) - { + while (sdi.hasNext()) { + if ( !firstTime ) { sb.append(" "); } firstTime = false; String s = sdi.next(); - if (null == s) - { + if ( null == s ) { s = "null"; } sb.append(s); @@ -254,14 +219,12 @@ public void testSortedDiffIterator() } - private static Binding build(String string) - { - Item item = SSE.parse("(binding "+string+")") ; - return BuilderBinding.build(item) ; + private static Binding build(String string) { + Item item = SSE.parse("(binding " + string + ")"); + return BuilderBinding.build(item); } - private Binding randomBinding(Var[] vars) - { + private Binding randomBinding(Var[] vars) { BindingBuilder builder = Binding.builder(); builder.add(vars[0], NodeFactory.createBlankNode()); builder.add(vars[1], NodeFactory.createURI(randomURI())); @@ -276,15 +239,13 @@ private Binding randomBinding(Var[] vars) return builder.build(); } - public String randomURI() - { + public String randomURI() { return String.format("http://%s.example.com/%s", randomString(10), randomString(10)); } - public String randomString(int length) - { + public String randomString(int length) { StringBuilder builder = new StringBuilder(); - for(int i = 0; i < length; i++){ + for ( int i = 0 ; i < length ; i++ ) { builder.append(LETTERS.charAt(random.nextInt(LETTERS.length()))); } return builder.toString(); diff --git a/jena-arq/src/test/java/org/apache/jena/atlas/data/TestSortedDataBag.java b/jena-arq/src/test/java/org/apache/jena/atlas/data/TestSortedDataBag.java index 662a6a4269e..68aa27bf02c 100644 --- a/jena-arq/src/test/java/org/apache/jena/atlas/data/TestSortedDataBag.java +++ b/jena-arq/src/test/java/org/apache/jena/atlas/data/TestSortedDataBag.java @@ -42,13 +42,12 @@ public class TestSortedDataBag private static final String LETTERS = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"; private Random random; - @Test public void testSorting() - { + @Test + public void testSorting() { testSorting(500, 10); } - private void testSorting(int numBindings, int threshold) - { + private void testSorting(int numBindings, int threshold) { List unsorted = randomBindings(numBindings); List conditions = new ArrayList<>(); @@ -59,22 +58,16 @@ private void testSorting(int numBindings, int threshold) List sorted = new ArrayList<>(); - SortedDataBag db = new SortedDataBag<>( - new ThresholdPolicyCount(threshold), - SerializationFactoryFinder.bindingSerializationFactory(), - comparator); - try - { + SortedDataBag db = new SortedDataBag<>(new ThresholdPolicyCount(threshold), + SerializationFactoryFinder.bindingSerializationFactory(), comparator); + try { db.addAll(unsorted); Iterator iter = db.iterator(); - while (iter.hasNext()) - { + while (iter.hasNext()) { sorted.add(iter.next()); } Iter.close(iter); - } - finally - { + } finally { db.close(); } @@ -82,13 +75,13 @@ private void testSorting(int numBindings, int threshold) assertEquals(unsorted, sorted); } - @Test public void testSortingWithPreMerge() - { + @Test + public void testSortingWithPreMerge() { // Save the original value... int origMaxSpillFiles = SortedDataBag.MAX_SPILL_FILES; - try - { + try { // Vary the number of spill files and bindings so we get a variable number of premerge rounds + // @formatter:off SortedDataBag.MAX_SPILL_FILES = 2; testSorting(1, 1); SortedDataBag.MAX_SPILL_FILES = 2; testSorting(2, 1); SortedDataBag.MAX_SPILL_FILES = 2; testSorting(3, 1); @@ -99,37 +92,31 @@ private void testSorting(int numBindings, int threshold) SortedDataBag.MAX_SPILL_FILES = 100; testSorting(1000, 10); SortedDataBag.MAX_SPILL_FILES = 2; testSorting(10, 10); SortedDataBag.MAX_SPILL_FILES = 5; testSorting(10, 10); - } - finally - { + // @formatter:on + } finally { SortedDataBag.MAX_SPILL_FILES = origMaxSpillFiles; } } - @Test public void testTemporaryFilesAreCleanedUpAfterCompletion() - { + @Test + public void testTemporaryFilesAreCleanedUpAfterCompletion() { List unsorted = randomBindings(500); List conditions = new ArrayList<>(); conditions.add(new SortCondition(new ExprVar("8"), Query.ORDER_ASCENDING)); BindingComparator comparator = new BindingComparator(conditions); - SortedDataBag db = new SortedDataBag<>( - new ThresholdPolicyCount(10), - SerializationFactoryFinder.bindingSerializationFactory(), - comparator); + SortedDataBag db = new SortedDataBag<>(new ThresholdPolicyCount(10), + SerializationFactoryFinder.bindingSerializationFactory(), comparator); List spillFiles = new ArrayList<>(); - try - { + try { db.addAll(unsorted); spillFiles.addAll(db.getSpillFiles()); int count = 0; - for (File file : spillFiles) - { - if (file.exists()) - { + for ( File file : spillFiles ) { + if ( file.exists() ) { count++; } } @@ -137,46 +124,36 @@ private void testSorting(int numBindings, int threshold) assertEquals(49, count); Iterator iter = db.iterator(); - while (iter.hasNext()) - { + while (iter.hasNext()) { iter.next(); } Iter.close(iter); - } - finally - { + } finally { db.close(); } int count = 0; - for (File file : spillFiles) - { - if (file.exists()) - { + for ( File file : spillFiles ) { + if ( file.exists() ) { count++; } } assertEquals(0, count); } - private List randomBindings(int numBindings) - { + private List randomBindings(int numBindings) { random = new Random(); - Var[] vars = new Var[]{ - Var.alloc("1"), Var.alloc("2"), Var.alloc("3"), - Var.alloc("4"), Var.alloc("5"), Var.alloc("6"), - Var.alloc("7"), Var.alloc("8"), Var.alloc("9"), Var.alloc("0") - }; + Var[] vars = new Var[]{Var.alloc("1"), Var.alloc("2"), Var.alloc("3"), Var.alloc("4"), Var.alloc("5"), Var.alloc("6"), + Var.alloc("7"), Var.alloc("8"), Var.alloc("9"), Var.alloc("0")}; List toReturn = new ArrayList<>(); - for(int i = 0; i < numBindings; i++){ + for ( int i = 0 ; i < numBindings ; i++ ) { toReturn.add(randomBinding(vars)); } return toReturn; } - private Binding randomBinding(Var[] vars) - { + private Binding randomBinding(Var[] vars) { BindingBuilder builder = Binding.builder(); builder.add(vars[0], NodeFactory.createBlankNode()); builder.add(vars[1], NodeFactory.createURI(randomURI())); @@ -191,30 +168,26 @@ private Binding randomBinding(Var[] vars) return builder.build(); } - private String randomURI() - { + private String randomURI() { return String.format("http://%s.example.com/%s", randomString(10), randomString(10)); } - private String randomString(int length) - { + private String randomString(int length) { StringBuilder builder = new StringBuilder(); - for(int i = 0; i < length; i++){ + for ( int i = 0 ; i < length ; i++ ) { builder.append(LETTERS.charAt(random.nextInt(LETTERS.length()))); } return builder.toString(); } - private void getNextAndExpectException(QueryIterator iter) - { - try{ + private void getNextAndExpectException(QueryIterator iter) { + try { iter.hasNext(); fail("Expected an exception here"); - }catch(QueryCancelledException e){ + } catch (QueryCancelledException e) { // expected - }catch(Exception e){ + } catch (Exception e) { fail("Unexpected exception"); } } - } diff --git a/jena-arq/src/test/java/org/apache/jena/atlas/data/TestThresholdPolicyCount.java b/jena-arq/src/test/java/org/apache/jena/atlas/data/TestThresholdPolicyCount.java index 1c6d5dd3257..c45f398c3a6 100644 --- a/jena-arq/src/test/java/org/apache/jena/atlas/data/TestThresholdPolicyCount.java +++ b/jena-arq/src/test/java/org/apache/jena/atlas/data/TestThresholdPolicyCount.java @@ -21,29 +21,24 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import org.junit.Test ; +import org.junit.Test; +public class TestThresholdPolicyCount { -public class TestThresholdPolicyCount -{ - @Test - public void count_01() - { + public void count_01() { ThresholdPolicyCount policy = new ThresholdPolicyCount<>(0); assertTrue(policy.isThresholdExceeded()); } - + @Test - public void count_02() - { + public void count_02() { ThresholdPolicyCount policy = new ThresholdPolicyCount<>(1); assertFalse(policy.isThresholdExceeded()); } - + @Test - public void count_03() - { + public void count_03() { ThresholdPolicyCount policy = new ThresholdPolicyCount<>(1); assertFalse(policy.isThresholdExceeded()); policy.increment("a"); diff --git a/jena-arq/src/test/java/org/apache/jena/riot/protobuf/TestProtobufResultSet.java b/jena-arq/src/test/java/org/apache/jena/riot/protobuf/TestProtobufResultSet.java index 4f554154c03..5cef3bf5fe1 100644 --- a/jena-arq/src/test/java/org/apache/jena/riot/protobuf/TestProtobufResultSet.java +++ b/jena-arq/src/test/java/org/apache/jena/riot/protobuf/TestProtobufResultSet.java @@ -33,7 +33,7 @@ import org.apache.jena.query.ResultSetRewindable; import org.apache.jena.riot.resultset.ResultSetLang; import org.apache.jena.sparql.exec.RowSet; -import org.apache.jena.sparql.resultset.ResultSetCompare; +import org.apache.jena.sparql.resultset.ResultsCompare; import org.apache.jena.sparql.sse.Item; import org.apache.jena.sparql.sse.SSE; import org.apache.jena.sparql.sse.builders.BuilderRowSet; @@ -75,7 +75,7 @@ public class TestProtobufResultSet { // not reordered r1.reset(); rs2.reset() ; - assertFalse(ResultSetCompare.equalsByTermAndOrder(r1, rs2)) ; + assertFalse(ResultsCompare.equalsByTermAndOrder(r1, rs2)) ; rs2.reset() ; } @@ -84,7 +84,7 @@ public class TestProtobufResultSet { // not reordered r2.reset(); rs1.reset() ; - assertFalse(ResultSetCompare.equalsByTermAndOrder(r2, rs1)) ; + assertFalse(ResultsCompare.equalsByTermAndOrder(r2, rs1)) ; rs1.reset() ; } @@ -98,7 +98,7 @@ private static ResultSetRewindable test(ResultSetRewindable resultSet) { RowSet rs$ = ProtobufRDF.readRowSet(in) ; ResultSetRewindable resultSet2 = ResultSetFactory.makeRewindable(rs$) ; // Includes bnode labels. - ResultSetCompare.equalsExact(resultSet, resultSet2) ; + ResultsCompare.equalsExact(resultSet, resultSet2) ; resultSet.reset(); resultSet2.reset(); return resultSet2 ; diff --git a/jena-arq/src/test/java/org/apache/jena/riot/resultset/TestResultSetIO.java b/jena-arq/src/test/java/org/apache/jena/riot/resultset/TestResultSetIO.java index b3f465619d3..4fe4f4f5b03 100644 --- a/jena-arq/src/test/java/org/apache/jena/riot/resultset/TestResultSetIO.java +++ b/jena-arq/src/test/java/org/apache/jena/riot/resultset/TestResultSetIO.java @@ -39,7 +39,7 @@ import org.apache.jena.query.ResultSetRewindable ; import org.apache.jena.riot.Lang ; import org.apache.jena.riot.ResultSetMgr ; -import org.apache.jena.sparql.resultset.ResultSetCompare ; +import org.apache.jena.sparql.resultset.ResultsCompare ; import org.apache.jena.sparql.sse.SSE ; import org.apache.jena.sparql.sse.builders.BuilderRowSet; @@ -97,7 +97,7 @@ public TestResultSetIO(String name, Lang lang) { ResultSetRewindable rsw = ResultSetFactory.makeRewindable(rs) ; if ( ! lang.equals(RS_CSV) ) { // CSV is not faithful - assertTrue(ResultSetCompare.equalsByTerm(test_rs, rsw)) ; + assertTrue(ResultsCompare.equalsByTerm(test_rs, rsw)) ; } rsw.reset(); @@ -109,7 +109,7 @@ public TestResultSetIO(String name, Lang lang) { rsw.reset(); in = new ByteArrayInputStream(out2.toByteArray()) ; ResultSet rs2 = ResultSetMgr.read(in, lang) ; - assertTrue(ResultSetCompare.equalsByTerm(rsw, rs2)) ; + assertTrue(ResultsCompare.equalsByTerm(rsw, rs2)) ; } } diff --git a/jena-arq/src/test/java/org/apache/jena/riot/thrift/TestThriftResultSet.java b/jena-arq/src/test/java/org/apache/jena/riot/thrift/TestThriftResultSet.java index c878a96c875..867b87ff8eb 100644 --- a/jena-arq/src/test/java/org/apache/jena/riot/thrift/TestThriftResultSet.java +++ b/jena-arq/src/test/java/org/apache/jena/riot/thrift/TestThriftResultSet.java @@ -33,7 +33,7 @@ import org.apache.jena.query.ResultSetRewindable ; import org.apache.jena.riot.resultset.ResultSetLang; import org.apache.jena.sparql.exec.RowSet; -import org.apache.jena.sparql.resultset.ResultSetCompare ; +import org.apache.jena.sparql.resultset.ResultsCompare ; import org.apache.jena.sparql.sse.SSE ; import org.junit.Test ; @@ -70,7 +70,7 @@ public class TestThriftResultSet { // not reordered r1.reset(); rs2.reset() ; - assertFalse(ResultSetCompare.equalsByTermAndOrder(r1, rs2)) ; + assertFalse(ResultsCompare.equalsByTermAndOrder(r1, rs2)) ; rs2.reset() ; } @@ -79,7 +79,7 @@ public class TestThriftResultSet { // not reordered r2.reset(); rs1.reset() ; - assertFalse(ResultSetCompare.equalsByTermAndOrder(r2, rs1)) ; + assertFalse(ResultsCompare.equalsByTermAndOrder(r2, rs1)) ; rs1.reset() ; } @@ -93,7 +93,7 @@ private static ResultSetRewindable test(ResultSetRewindable resultSet) { RowSet rs$ = ThriftRDF.readRowSet(in) ; ResultSetRewindable resultSet2 = ResultSetFactory.makeRewindable(rs$) ; // Includes bnode labels. - ResultSetCompare.equalsExact(resultSet, resultSet2) ; + ResultsCompare.equalsExact(resultSet, resultSet2) ; resultSet.reset(); resultSet2.reset(); return resultSet2 ; diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/AbstractTestAdditional.java b/jena-arq/src/test/java/org/apache/jena/sparql/AbstractTestAdditional.java index 6e558d83645..3d246991110 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/AbstractTestAdditional.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/AbstractTestAdditional.java @@ -27,7 +27,7 @@ import org.apache.jena.sparql.exec.QueryExec; import org.apache.jena.sparql.exec.RowSetOps; import org.apache.jena.sparql.exec.RowSetRewindable; -import org.apache.jena.sparql.resultset.ResultSetCompare; +import org.apache.jena.sparql.resultset.ResultsCompare; import org.apache.jena.sparql.sse.SSE; import org.apache.jena.system.Txn; import org.junit.Test; @@ -70,7 +70,7 @@ public abstract class AbstractTestAdditional { } private static void testRS(RowSetRewindable rsExpected, RowSetRewindable rsGot) { - boolean b = ResultSetCompare.equalsByTerm(rsExpected, rsGot); + boolean b = ResultsCompare.equalsByTerm(rsExpected, rsGot); if (! b ) { rsExpected.reset(); rsGot.reset(); diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/TC_ARQ.java b/jena-arq/src/test/java/org/apache/jena/sparql/TC_ARQ.java index 4048ca23b96..6ef29163441 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/TC_ARQ.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/TC_ARQ.java @@ -52,6 +52,7 @@ import org.apache.jena.sparql.transaction.TS_Transaction ; import org.apache.jena.sparql.util.TS_DyadicDatasetGraphs; import org.apache.jena.sparql.util.TS_Util ; +import org.apache.jena.sparql.util.iso.TS_Iso ; import org.apache.jena.sparql.util.compose.TS_DatasetCollectors; import org.junit.AfterClass ; import org.junit.BeforeClass ; @@ -67,6 +68,7 @@ , TS_DyadicDatasetGraphs.class , TS_DatasetCollectors.class , TS_Util.class + , TS_Iso.class , TS_Expr.class , TS_LibraryFunctions.class @@ -97,7 +99,7 @@ // Outside org.apache.jena.sparql , TS_Query.class - + // RDF 1.2 tests. These track the working group. , TS_RDF12.class // And scripted tests. diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestSemanticEquivalence.java b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestSemanticEquivalence.java index 159aff26972..f9a30565a00 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestSemanticEquivalence.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestSemanticEquivalence.java @@ -34,7 +34,7 @@ import org.apache.jena.sparql.engine.ResultSetStream ; import org.apache.jena.sparql.engine.binding.BindingFactory ; import org.apache.jena.sparql.engine.main.QueryEngineMain ; -import org.apache.jena.sparql.resultset.ResultSetCompare ; +import org.apache.jena.sparql.resultset.ResultsCompare ; import org.apache.jena.sparql.sse.SSE ; import org.apache.jena.sparql.util.Symbol ; import org.junit.AfterClass ; @@ -204,7 +204,7 @@ public static void test(String queryStr, Dataset ds, Symbol opt, int expected) { } Assert.assertEquals(expected, rsOpt.size()); } - Assert.assertTrue(ResultSetCompare.isomorphic(rs, rsOpt)); + Assert.assertTrue(ResultsCompare.equalsByTerm(rs, rsOpt)); } finally { // Restore previous state if (isEnabled) { @@ -268,7 +268,7 @@ public static void testAsAlgebra(String algStr, Dataset ds, Symbol opt, int expe Assert.assertEquals(expected, rsOpt.size()); iterOpt.close(); - Assert.assertTrue(ResultSetCompare.isomorphic(rs, rsOpt)); + Assert.assertTrue(ResultsCompare.equalsByTerm(rs, rsOpt)); } finally { // Restore previous state if (isEnabled) { diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/binding/TestBindingStreams.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/binding/TestBindingStreams.java index 69d787d8c6d..8f15f9bf902 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/engine/binding/TestBindingStreams.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/engine/binding/TestBindingStreams.java @@ -26,6 +26,10 @@ import java.util.ArrayList ; import java.util.List ; +import org.junit.AfterClass ; +import org.junit.BeforeClass ; +import org.junit.Test ; + import org.apache.jena.atlas.legacy.BaseTest2 ; import org.apache.jena.graph.Node ; import org.apache.jena.graph.NodeFactory ; @@ -36,15 +40,9 @@ import org.apache.jena.riot.tokens.TokenizerText; import org.apache.jena.sparql.core.Var ; import org.apache.jena.sparql.graph.NodeConst ; -import org.apache.jena.sparql.resultset.ResultSetCompare ; import org.apache.jena.sparql.sse.Item ; import org.apache.jena.sparql.sse.SSE ; import org.apache.jena.sparql.sse.builders.BuilderBinding ; -import org.apache.jena.sparql.util.NodeUtils ; -import org.junit.AfterClass ; -import org.junit.BeforeClass ; -import org.junit.Test ; - public class TestBindingStreams { @@ -106,82 +104,70 @@ public void bindingStream_12() { @Test public void bindingStream_60() { testWriteRead(bb1) ; } @Test - public void bindingStream_61() - { - Node bn = NodeFactory.createBlankNode("unusual") ; - Binding b = BindingFactory.binding(Var.alloc("v"), bn) ; - testWriteRead(b) ; + public void bindingStream_61() { + Node bn = NodeFactory.createBlankNode("unusual"); + Binding b = BindingFactory.binding(Var.alloc("v"), bn); + testWriteRead(b); } @Test public void bindingStream_62() { testWriteRead(bb2) ; } @Test public void bindingStream_63() { testWriteRead(bb3) ; } + static void testRead(String x, Binding...bindings) { + Tokenizer t = TokenizerText.create().fromString(x).build();; + BindingInputStream inStream = new BindingInputStream(t); - static void testRead(String x, Binding ... bindings) - { - Tokenizer t = TokenizerText.create().fromString(x).build(); ; - BindingInputStream inStream = new BindingInputStream(t) ; - - if ( bindings.length == 0 ) - { + if ( bindings.length == 0 ) { for ( ; inStream.hasNext() ; ) - inStream.next() ; - return ; + inStream.next(); + return; } - int i ; - for ( i = 0 ; inStream.hasNext() ; i++ ) - { - Binding b = inStream.next() ; - assertTrue("Bindings do not match: expected="+bindings[i]+" got="+b, equalBindings(bindings[i], b)) ; + int i; + for ( i = 0 ; inStream.hasNext() ; i++ ) { + Binding b = inStream.next(); + assertTrue("Bindings do not match: expected=" + bindings[i] + " got=" + b, equalBindings(bindings[i], b)); } - assertEquals("Wrong length: expect= "+bindings.length+" got="+i,bindings.length, i) ; + assertEquals("Wrong length: expect= " + bindings.length + " got=" + i, bindings.length, i); } static void testWriteRead(Binding ... bindings) { testWriteRead(null, bindings) ; } - static void testWriteRead(PrefixMap prefixMap, Binding ... bindings) - { - ByteArrayOutputStream out = new ByteArrayOutputStream() ; - BindingOutputStream output = new BindingOutputStream(out, prefixMap) ; + static void testWriteRead(PrefixMap prefixMap, Binding...bindings) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BindingOutputStream output = new BindingOutputStream(out, prefixMap); for ( Binding b : bindings ) - output.write(b) ; - output.flush() ; + output.write(b); + output.flush(); // When the going gets tough, the tough put in trace statements: - //System.out.println("T: \n"+out.toString()) ; + // System.out.println("T: \n"+out.toString()) ; - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()) ; - BindingInputStream input = new BindingInputStream(in) ; + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + BindingInputStream input = new BindingInputStream(in); - List results = new ArrayList<>() ; - for ( ; input.hasNext() ; ) - { - results.add(input.next()) ; + List results = new ArrayList<>(); + for ( ; input.hasNext() ; ) { + results.add(input.next()); } - assertEquals(bindings.length, results.size()) ; - for ( int i = 0 ; i < bindings.length ; i++ ) - { - Binding b1 = bindings[i] ; - Binding b2 = results.get(i) ; - assertTrue("Bindings do not match: expected="+b1+" got="+b2, equalBindings(b1, b2)) ; + assertEquals(bindings.length, results.size()); + for ( int i = 0 ; i < bindings.length ; i++ ) { + Binding b1 = bindings[i]; + Binding b2 = results.get(i); + assertTrue("Bindings do not match: expected=" + b1 + " got=" + b2, equalBindings(b1, b2)); } } - - private static boolean equalBindings(Binding binding1, Binding binding2) - { - // Need to have the exact same terms coming back (therefore we can't use BNodeIso to compare values) - return ResultSetCompare.equal(binding1, binding2, NodeUtils.sameNode) ; + private static boolean equalBindings(Binding binding1, Binding binding2) { + // Identical + return BindingLib.equals(binding1, binding2) ; } - - private static Binding build(String string) - { - Item item = SSE.parse("(binding "+string+")") ; - return BuilderBinding.build(item) ; + private static Binding build(String string) { + Item item = SSE.parse("(binding " + string + ")"); + return BuilderBinding.build(item); } } diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestJoin.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestJoin.java index 350332965de..1ede7bc7970 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestJoin.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestJoin.java @@ -31,7 +31,7 @@ import org.apache.jena.sparql.engine.QueryIterator ; import org.apache.jena.sparql.engine.binding.Binding ; import org.apache.jena.sparql.expr.ExprList ; -import org.apache.jena.sparql.resultset.ResultSetCompare ; +import org.apache.jena.sparql.resultset.ResultsCompare ; import org.apache.jena.sparql.sse.SSE ; import org.junit.Assert ; @@ -338,7 +338,7 @@ protected static void print(IndentedWriter out, String label, Table table) { private static boolean equalTables(Table table1, Table table2) { ResultSet rs1 = ResultSetFactory.create(table1.iterator(null), table1.getVarNames()) ; ResultSet rs2 = ResultSetFactory.create(table2.iterator(null), table2.getVarNames()) ; - return ResultSetCompare.equalsByTerm(rs1, rs2) ; + return ResultsCompare.equalsByTerm(rs1, rs2) ; } } diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestTableJoin.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestTableJoin.java index 3b206254b14..77a6358073d 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestTableJoin.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestTableJoin.java @@ -35,7 +35,7 @@ import org.apache.jena.sparql.engine.QueryIterator ; import org.apache.jena.sparql.engine.ref.TableJoin; import org.apache.jena.sparql.expr.ExprList ; -import org.apache.jena.sparql.resultset.ResultSetCompare ; +import org.apache.jena.sparql.resultset.ResultsCompare ; import org.apache.jena.sparql.sse.SSE ; /** Tests on tables and the simple nest loop join (TableJoin) used by the reference query engine */ @@ -115,7 +115,7 @@ static class TableCompare { public static boolean equalsByTerm(Table table1, Table table2) { ResultSet rs1 = ResultSetFactory.create(table1.iterator(null), table1.getVarNames()) ; ResultSet rs2 = ResultSetFactory.create(table2.iterator(null), table2.getVarNames()) ; - return ResultSetCompare.equalsByTerm(rs1, rs2) ; + return ResultsCompare.equalsByTerm(rs1, rs2) ; } } diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/path/TestPathQuery.java b/jena-arq/src/test/java/org/apache/jena/sparql/path/TestPathQuery.java index 26071d5dc0a..26ce2c93ce6 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/path/TestPathQuery.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/path/TestPathQuery.java @@ -27,7 +27,8 @@ import org.apache.jena.riot.Lang; import org.apache.jena.riot.RDFParser; import org.apache.jena.sparql.exec.*; -import org.apache.jena.sparql.resultset.ResultSetCompare; +import org.apache.jena.sparql.resultset.ResultsCompare; + import org.junit.Test; /** Path tests using queries. */ @@ -75,7 +76,7 @@ public class TestPathQuery { } @Test public void testPathByQuery_unboundEnds_05() { - String qsPath = "PREFIX : SELECT * { ?s :p{1,3} ?o }"; + String qsPath = "PREFIX : SELECT ?s ?o { ?s :p{1,3} ?o }"; // Same results for the test data, not in general. String qsExpected = "PREFIX : SELECT ?s ?o { { ?s :p ?o } UNION { ?s :p [:p ?o]} }"; test(graph1, qsPath, qsExpected); @@ -91,6 +92,7 @@ private void test(Graph graph12, String qsPath, String qsExpected) { System.out.println(qsPath); print("Actual", rs1); print("Expected", rs2); + rowSetEquals(rs1, rs2); } assertTrue(same); } @@ -102,7 +104,8 @@ private RowSetRewindable exec(Graph g, String qs) { } private boolean rowSetEquals(RowSetRewindable rowset1, RowSetRewindable rowset2) { - return ResultSetCompare.equalsByTerm(rowset1, rowset2); + // XXX [ISO] Use exact. + return ResultsCompare.equalsExact(rowset1, rowset2); } private void print(String label, RowSetRewindable rowset) { diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultSet.java b/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultSet.java index 1f2cbd9450c..5b2d9b0d56b 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultSet.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultSet.java @@ -82,7 +82,7 @@ public void test_RS_1() { ByteArrayInputStream ins = new ByteArrayInputStream(arr.toByteArray()); ResultSet rs2 = ResultSetFactory.fromXML(ins); - assertTrue(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertTrue(ResultsCompare.equalsByTerm(rs1, rs2)); } @Test @@ -92,7 +92,7 @@ public void test_RS_1_str() { rs1.reset(); InputStream in = new ByteArrayInputStream(StrUtils.asUTF8bytes(x)); ResultSet rs2 = ResultSetFactory.fromXML(in); - assertTrue(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertTrue(ResultsCompare.equalsByTerm(rs1, rs2)); } @Test @@ -103,7 +103,7 @@ public void test_RS_2() { rs1.reset(); ByteArrayInputStream ins = new ByteArrayInputStream(arr.toByteArray()); ResultSet rs2 = ResultSetFactory.fromXML(ins); - assertTrue(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertTrue(ResultsCompare.equalsByTerm(rs1, rs2)); } @Test @@ -113,7 +113,7 @@ public void test_RS_2_str() { rs1.reset(); InputStream in = new ByteArrayInputStream(StrUtils.asUTF8bytes(x)); ResultSet rs2 = ResultSetFactory.fromXML(in); - assertTrue(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertTrue(ResultsCompare.equalsByTerm(rs1, rs2)); } // RDF @@ -124,7 +124,7 @@ public void test_RS_3() { Model model = RDFOutput.encodeAsModel(rs1); rs1.reset(); ResultSet rs2 = RDFInput.fromRDF(model); - assertTrue(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertTrue(ResultsCompare.equalsByTerm(rs1, rs2)); } @Test @@ -133,7 +133,7 @@ public void test_RS_4() { Model model = RDFOutput.encodeAsModel(rs1); rs1.reset(); ResultSetRewindable rs2 = ResultSetFactory.makeRewindable(RDFInput.fromRDF(model)); - boolean b = ResultSetCompare.equalsByTerm(rs1, rs2); + boolean b = ResultsCompare.equalsByTerm(rs1, rs2); if ( !b ) { rs1.reset(); rs2.reset(); @@ -154,7 +154,7 @@ public void test_RS_5() { rs1.reset(); ByteArrayInputStream ins = new ByteArrayInputStream(arr.toByteArray()); ResultSet rs2 = ResultSetFactory.fromJSON(ins); - assertTrue(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertTrue(ResultsCompare.equalsByTerm(rs1, rs2)); } @Test @@ -166,7 +166,7 @@ public void test_RS_6() { ByteArrayInputStream ins = new ByteArrayInputStream(arr.toByteArray()); ResultSet rs2 = ResultSetFactory.fromJSON(ins); // Test using the DAWG // examples - assertTrue(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertTrue(ResultsCompare.equalsByTerm(rs1, rs2)); } // Into some format. @@ -225,7 +225,7 @@ public void test_RS_union_1() { ResultSet rs1 = make("x", org.apache.jena.graph.NodeFactory.createURI("tag:local")); ResultSet rs2 = make("x", org.apache.jena.graph.NodeFactory.createURI("tag:local")); ResultSet rs3 = make2("x", org.apache.jena.graph.NodeFactory.createURI("tag:local")); - assertTrue(ResultSetCompare.equalsByTerm(rs3, ResultSetUtils.merge(rs1, rs2))); + assertTrue(ResultsCompare.equalsByTerm(rs3, ResultSetUtils.merge(rs1, rs2))); } private void test_RS_fmt(ResultSet rs, ResultsFormat fmt, boolean ordered) { @@ -238,11 +238,11 @@ private void test_RS_fmt(ResultSet rs, ResultsFormat fmt, boolean ordered) { ResultSetRewindable rs2 = ResultSetFactory.makeRewindable(ResultSetFactory.load(ins, fmt)); // Ordered? Unordered? - boolean b = ResultSetCompare.equalsByTerm(rs1, rs2); + boolean b = ResultsCompare.equalsByTerm(rs1, rs2); if ( ordered ) { rs1.reset(); rs2.reset(); - b = b & ResultSetCompare.equalsByTerm(rs1, rs2); + b = b & ResultsCompare.equalsByTerm(rs1, rs2); } if ( !b ) { @@ -261,17 +261,17 @@ private void test_RS_fmt(ResultSet rs, ResultsFormat fmt, boolean ordered) { public void test_RS_cmp_1() { ResultSetRewindable rs1 = new ResultSetMem(); ResultSetRewindable rs2 = new ResultSetMem(); - assertTrue(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertTrue(ResultsCompare.equalsByTerm(rs1, rs2)); rs1.reset(); rs2.reset(); - assertTrue(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertTrue(ResultsCompare.equalsByTerm(rs1, rs2)); } @Test public void test_RS_cmp_2() { ResultSet rs1 = make("x", org.apache.jena.graph.NodeFactory.createURI("tag:local")); ResultSet rs2 = new ResultSetMem(); - assertFalse(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertFalse(ResultsCompare.equalsByTerm(rs1, rs2)); } @@ -279,15 +279,15 @@ public void test_RS_cmp_2() { public void test_RS_cmp_3() { ResultSet rs1 = make("x", org.apache.jena.graph.NodeFactory.createURI("tag:local")); ResultSet rs2 = new ResultSetMem(); - assertFalse(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertFalse(ResultsCompare.equalsByTerm(rs1, rs2)); } @Test public void test_RS_cmp_4() { ResultSet rs1 = make("x", org.apache.jena.graph.NodeFactory.createURI("tag:local")); ResultSet rs2 = make("x", org.apache.jena.graph.NodeFactory.createURI("tag:local")); - assertTrue(ResultSetCompare.equalsByTerm(rs1, rs2)); - assertTrue(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertTrue(ResultsCompare.equalsByTerm(rs1, rs2)); + assertTrue(ResultsCompare.equalsByTerm(rs1, rs2)); } @Test @@ -296,13 +296,13 @@ public void test_RS_cmp_5() { ResultSetRewindable rs1 = makeRewindable("x", org.apache.jena.graph.NodeFactory.createURI("tag:local:1")); ResultSetRewindable rs2 = makeRewindable("x", org.apache.jena.graph.NodeFactory.createURI("tag:local:2")); - assertFalse(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertFalse(ResultsCompare.equalsByTerm(rs1, rs2)); rs1.reset(); rs2.reset(); assertTrue(rs1.hasNext()); assertTrue(rs2.hasNext()); - assertFalse(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertFalse(ResultsCompare.equalsByTerm(rs1, rs2)); } @Test @@ -310,12 +310,12 @@ public void test_RS_cmp_6() { // Different variable, same values ResultSetRewindable rs1 = makeRewindable("x", org.apache.jena.graph.NodeFactory.createURI("tag:local")); ResultSetRewindable rs2 = makeRewindable("y", org.apache.jena.graph.NodeFactory.createURI("tag:local")); - assertFalse(ResultSetCompare.equalsByTermAndOrder(rs1, rs2)); + assertFalse(ResultsCompare.equalsByTermAndOrder(rs1, rs2)); rs1.reset(); rs2.reset(); assertTrue(rs1.hasNext()); assertTrue(rs2.hasNext()); - assertFalse(ResultSetCompare.equalsByTerm(rs1, rs2)); + assertFalse(ResultsCompare.equalsByTerm(rs1, rs2)); } // Value based @@ -323,8 +323,8 @@ public void test_RS_cmp_6() { public void test_RS_cmp_value_1() { ResultSetRewindable rs1 = makeRewindable("x", NodeFactoryExtra.parseNode("123")); ResultSetRewindable rs2 = makeRewindable("x", NodeFactoryExtra.parseNode("0123")); - assertFalse(ResultSetCompare.equalsByTerm(rs1, rs2)); - assertTrue(ResultSetCompare.equalsByValue(rs1, rs2)); + assertFalse(ResultsCompare.equalsByTerm(rs1, rs2)); + assertTrue(ResultsCompare.equalsByValue(rs1, rs2)); } // Peeking @@ -503,25 +503,19 @@ public void test_RS_peeking_9() { // ---- Isomorphism. - /* This is from the DAWG test suite. Result set 1: --------------- | x | y | - * =============== | _:b0 | _:b1 | | _:b2 | _:b3 | | _:b1 | _:b0 | - * --------------- Result set 2: --------------- | x | y | =============== | _:b1 - * | _:b0 | | _:b3 | _:b2 | | _:b2 | _:b3 | --------------- */ - - // nasty result set. - // These are the same but the first row of rs2$ throws in a wrong mapping of - // b0/c1 - - // Right mapping is: - // b0->c3, b1->c2, b2->c1, b3->c0 - // Currently we get, working simply top to bottom, no backtracking: - // b0->c1, b1->c0, b2->c3, b3->c2, then last row fails as _:b1 is mapped to c0, - // b0 to c1 not (c2, c3) - - private static String[] rs1$ = {"(resultset (?x ?y)", " (row (?x _:b0) (?y _:b1))", " (row (?x _:b2) (?y _:b3))", - " (row (?x _:b1) (?y _:b0))", ")"}; - private static String[] rs2$ = {"(resultset (?x ?y)", " (row (?x _:c1) (?y _:c0))", " (row (?x _:c3) (?y _:c2))", - " (row (?x _:c2) (?y _:c3))", ")"}; + private static String[] rs1$ = { + "(resultset (?x ?y)", + " (row (?x _:b0) (?y _:b1))", + " (row (?x _:b2) (?y _:b3))", + " (row (?x _:b1) (?y _:b0))", + ")" + }; + private static String[] rs2$ = { + "(resultset (?x ?y)", + " (row (?x _:c1) (?y _:c0))", + " (row (?x _:c3) (?y _:c2))", + " (row (?x _:c2) (?y _:c3))", + ")"}; @Test public void test_RS_iso_1() { @@ -531,14 +525,10 @@ public void test_RS_iso_1() { private void isotest(String[] rs1$2, String[] rs2$2) { ResultSetRewindable rs1 = make(StrUtils.strjoinNL(rs1$)); ResultSetRewindable rs2 = make(StrUtils.strjoinNL(rs2$)); - - assertTrue(ResultSetCompare.isomorphic(rs1, rs2)); + assertTrue(ResultsCompare.equalsByTerm(rs1, rs2)); rs1.reset(); rs2.reset(); - assertTrue(ResultSetCompare.equalsByTerm(rs1, rs2)); - rs1.reset(); - rs2.reset(); - assertTrue(ResultSetCompare.equalsByValue(rs1, rs2)); + assertTrue(ResultsCompare.equalsByValue(rs1, rs2)); } private static ResultSetRewindable make(String x) { @@ -580,12 +570,14 @@ private static void preserve_bnodes(Lang sparqlresultlang, Context cxt, boolean ByteArrayInputStream y = new ByteArrayInputStream(x.toByteArray()); ResultSetRewindable rs2 = ResultSetFactory.copyResults(ResultsReader.create().context(cxt).lang(sparqlresultlang).read(y)); + rs1.reset(); rs2.reset(); + if ( same ) - assertTrue(ResultSetCompare.equalsExact(rs1, rs2)); + assertTrue(ResultsCompare.equalsExact(rs1, rs2)); else - assertFalse(ResultSetCompare.equalsExact(rs1, rs2)); + assertFalse(ResultsCompare.equalsExact(rs1, rs2)); } // -------- Support functions diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultSetFormat1.java b/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultSetFormat1.java index 707f195a7f4..2bb6fd23a33 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultSetFormat1.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/resultset/TestResultSetFormat1.java @@ -112,81 +112,72 @@ public class TestResultSetFormat1 ")" } ; @Parameters - public static Collection data() - { + public static Collection data() { return Arrays.asList(new Object[][] { {$rs0}, {$rs1}, {$rs2}, {$rs3}, {$rs4}, {$rs5}, {$rs6}, {$rs7}, {$rs8}, {$rs9}, {$rs10}, {$rs11} } ) ; } private final String[] $rs ; - public TestResultSetFormat1(String[] rs) - { - this.$rs = rs ; + public TestResultSetFormat1(String[] rs) { + this.$rs = rs; } - static ResultSet make(String... strings) - { + static ResultSet make(String...strings) { if ( strings.length == 0 ) - throw new IllegalArgumentException() ; + throw new IllegalArgumentException(); - String x = StrUtils.strjoinNL(strings) ; - Item item = SSE.parse(x) ; + String x = StrUtils.strjoinNL(strings); + Item item = SSE.parse(x); return ResultSetFactory.makeRewindable(BuilderRowSet.build(item)); } - @Test public void resultset_01() - { - ResultSet rs = make($rs) ; - ResultSetFormatter.asText(rs) ; + @Test + public void resultset_01() { + ResultSet rs = make($rs); + ResultSetFormatter.asText(rs); } - @Test public void resultset_02() - { - ResultSet rs = make($rs) ; - ByteArrayOutputStream out = new ByteArrayOutputStream() ; - ResultSetFormatter.outputAsXML(out, rs) ; - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()) ; - ResultSet rs2 = ResultSetFactory.fromXML(in) ; + @Test + public void resultset_02() { + ResultSet rs = make($rs); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ResultSetFormatter.outputAsXML(out, rs); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + ResultSet rs2 = ResultSetFactory.fromXML(in); checkIsomorphic(rs, rs2); } - @Test public void resultset_03() - { - ResultSet rs = make($rs) ; - ByteArrayOutputStream out = new ByteArrayOutputStream() ; - ResultSetFormatter.outputAsJSON(out, rs) ; - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()) ; - ResultSet rs2 = ResultSetFactory.fromJSON(in) ; + @Test + public void resultset_03() { + ResultSet rs = make($rs); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ResultSetFormatter.outputAsJSON(out, rs); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + ResultSet rs2 = ResultSetFactory.fromJSON(in); checkIsomorphic(rs, rs2); } - @Test public void resultset_04() - { - ResultSet rs = make($rs) ; - ByteArrayOutputStream out = new ByteArrayOutputStream() ; - ResultSetFormatter.outputAsTSV(out, rs) ; - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()) ; + @Test + public void resultset_04() { + ResultSet rs = make($rs); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ResultSetFormatter.outputAsTSV(out, rs); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); ResultSet rs2 = ResultSetMgr.read(in, ResultSetLang.RS_TSV); checkIsomorphic(rs, rs2); } - @Test public void resultset_05() - { - ResultSet rs = make($rs) ; - ByteArrayOutputStream out = new ByteArrayOutputStream() ; - ResultSetFormatter.outputAsCSV(out, rs) ; + @Test + public void resultset_05() { + ResultSet rs = make($rs); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ResultSetFormatter.outputAsCSV(out, rs); } - private static void checkIsomorphic(ResultSet x, ResultSet y) - { + private static void checkIsomorphic(ResultSet x, ResultSet y) { ResultSetRewindable rs1 = x.rewindable(); ResultSetRewindable rs2 = y.rewindable(); -// System.out.println(ResultSetFormatter.asText(rs1)); -// System.out.println(); -// System.out.println(ResultSetFormatter.asText(rs2)); -// rs1.reset(); -// rs2.reset(); - Assert.assertTrue(ResultSetCompare.isomorphic(rs1, rs2)) ; + Assert.assertTrue(ResultsCompare.equalsByTerm(rs1, rs2)); } } diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/util/TS_Util.java b/jena-arq/src/test/java/org/apache/jena/sparql/util/TS_Util.java index 248e96e3d92..64e3d9362fa 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/util/TS_Util.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/util/TS_Util.java @@ -28,7 +28,6 @@ TestList.class , TestFmtUtils.class, TestContextUtils.class, - TestIsoMatcher.class, TestGraphUtils.class, TestQueryCheckRW.class }) diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TS_Iso.java b/jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TS_Iso.java new file mode 100644 index 00000000000..ee160060dda --- /dev/null +++ b/jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TS_Iso.java @@ -0,0 +1,32 @@ +/* + * 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.sparql.util.iso; + +import org.junit.runner.RunWith ; +import org.junit.runners.Suite ; +import org.junit.runners.Suite.SuiteClasses ; + +@RunWith(Suite.class) +@SuiteClasses( { + TestIso.class, + TestIsoMatcher.class, + TestIsoAlgRows.class +}) + +public class TS_Iso { } diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TestIso.java b/jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TestIso.java new file mode 100644 index 00000000000..0c7dd01d66a --- /dev/null +++ b/jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TestIso.java @@ -0,0 +1,71 @@ +/* + * 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.sparql.util.iso; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import org.apache.jena.graph.Node; +import org.apache.jena.graph.Triple; +import org.apache.jena.sparql.sse.SSE; +import org.apache.jena.sparql.util.Iso; +import org.apache.jena.sparql.util.NodeIsomorphismMap; + +/** {@link Iso} contains atomic and order list matching. */ +public class TestIso { + + @Test public void iso_terms_iri_01() { testTerms(":s", ":s", true); } + @Test public void iso_terms_iri_02() { testTerms(":s", ":x", false); } + + @Test public void iso_terms_bnode_01() { testTerms("_:s", "_:x", true); } + @Test public void iso_terms_bnode_02() { testTerms("_:s", "_:s", true); } + + @Test public void iso_terms_literal_01() { testTerms("'abc'", "'abc'", true); } + @Test public void iso_terms_literal_02() { testTerms("'abc'", "'xyz'", false); } + + @Test public void iso_terms_tripleTerms_01() { testTerms("<<( :s :p :o )>>", "<<( :s :p :o )>>", true); } + @Test public void iso_terms_tripleTerms_02() { testTerms("<<(:s :p :z )>>", "<<( :s :p :o )>>", false); } + + @Test public void iso_terms_tripleTerms_03() { testTerms("<<( _:b :p :o )>>", "<<( _:x :p :o )>>", true); } + @Test public void iso_terms_tripleTerms_04() { testTerms("<<( _:b :p _:b )>>", "<<( _:x :p _:z )>>", false); } + + @Test public void iso_terms_50() { testTerms(":s", "_:b", false); } + + @Test public void iso_triples_01() { testTriples("(:s :p :o)", "(:s :p :o)", true); } + @Test public void iso_triples_02() { testTriples("(_:b :p :o)", "(_:x :p :o)", true); } + @Test public void iso_triples_03() { testTriples("(_:b :p :o)", "(:s :p _:b)", false); } + @Test public void iso_triples_04() { testTriples("(_:b :p _:b)", "(_:x1 :p _:x2)", false); } + + private void testTerms(String str1, String str2, boolean expected) { + Node n1 = SSE.parseNode(str1); + Node n2 = SSE.parseNode(str2); + NodeIsomorphismMap isoMap = new NodeIsomorphismMap(); + boolean result = Iso.nodeIso(n1, n2, isoMap); + assertEquals(expected, result); + } + + private void testTriples(String str1, String str2, boolean expected) { + Triple t1 = SSE.parseTriple(str1); + Triple t2 = SSE.parseTriple(str2); + NodeIsomorphismMap isoMap = new NodeIsomorphismMap(); + boolean result = Iso.tripleIso(t1, t2, isoMap); + assertEquals(expected, result); + } +} diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TestIsoAlgRows.java b/jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TestIsoAlgRows.java new file mode 100644 index 00000000000..7dd7dc054ec --- /dev/null +++ b/jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TestIsoAlgRows.java @@ -0,0 +1,351 @@ +/* + * 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.sparql.util.iso; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Test; + +import org.apache.jena.graph.Node; +import org.apache.jena.sparql.engine.binding.Binding; +import org.apache.jena.sparql.exec.RowSet; +import org.apache.jena.sparql.exec.RowSetMem; +import org.apache.jena.sparql.exec.RowSetRewindable; +import org.apache.jena.sparql.resultset.ResultsCompare; +import org.apache.jena.sparql.sse.SSE; +import org.apache.jena.sparql.util.EqualityTest; +import org.apache.jena.sparql.util.NodeUtils; + +public class TestIsoAlgRows { + + @Test public void testIsoTerm_01() { testIsoTerm(":s", ":s", true); } + @Test public void testIsoTerm_02() { testIsoTerm(":s", "'s'", false); } + @Test public void testIsoTerm_03() { testIsoTerm("_:b0", "_:b1", true); } + @Test public void testIsoTerm_04() { testIsoTerm("<<(_:b0 :p :o )>>", "<<(_:b1 :p :o )>>", true); } + + @Test + public void testIsoTerm_05() { + testIsoTerm("<<( _:b0 :p <<( _:b0 _:b0 _:b0 )>> )>>", "<<( _:b1 :p <<( _:b1 _:b1 _:b1 )>> )>>", true); + } + + @Test + public void testIsoTerm_06() { + testIsoTerm("<<( _:b0 :p <<( _:b0 _:b0 _:b0 )>> )>>", "<<( _:b1 :p <<( _:b1 _:b1 _:b2 )>> )>>", false); + } + + @Test + public void testIsoTerm_07() { + testIsoTerm("<<( _:b1 :p <<( _:b0 _:b0 _:b1 )>> )>>", "<<( _:b2 :p <<( _:b3 _:b3 _:b2 )>> )>>", true); + } + + @Test public void testIsoRowSet_01() { testIsoRowSet("(rowset (?x))", "(rowset (?x))", true); } + @Test public void testIsoRowSet_02() { testIsoRowSet("(rowset (?x))", "(rowset (?y))", false); } + @Test public void testIsoRowSet_03() { testIsoRowSet("(rowset (?x))", "(rowset (?x ?y))", false); } + @Test public void testIsoRowSet_04() { testIsoRowSet("(rowset (?x ?y))", "(rowset (?y ?x))", true); } + + @Test public void testIsoRowSet_10() { testIsoRowSet("(rowset (?x) (row (?x 'A')) )", "(rowset (?x) (row (?x 'A')) )", true); } + @Test public void testIsoRowSet_11() { testIsoRowSet("(rowset (?x) (row (?x 'A')) )", "(rowset (?y) (row (?y 'A')) )", false); } + @Test public void testIsoRowSet_12() { testIsoRowSet("(rowset (?x) (row (?x 'A')) )", "(rowset (?x) (row (?x 'A')) )", true); } + @Test public void testIsoRowSet_13() { testIsoRowSet("(rowset (?x) (row (?x 'A')) )", "(rowset (?x) (row (?x 'A')) )", true); } + + @Test public void testIsoRowSet_14() { testIsoRowSet("(rowset (?x ?y))", "(rowset (?y ?x) (row) )", false); } + @Test public void testIsoRowSet_15() { testIsoRowSet("(rowset (?x) (row (?x 'A')) )", "(rowset (?x) (row (?x 'A')) (row) )", false); } + + @Test public void testIsoRowSet_16() { + testIsoRowSet("(rowset (?x ?y) (row (?x 'A') (?y 'B')) )", + "(rowset (?x ?y) (row (?y 'B') (?x 'A')) )", + true); + } + + // Blank nodes, one row + + @Test public void testIsoRowSet_21() { + testIsoRowSet("(rowset (?x ?y ?z) (row (?x _:b0) (?y _:b1) (?z _:b2)) )", + "(rowset (?x ?y ?z) (row (?x _:c0) (?y _:c1) (?z _:c2)) )", + true); } + + @Test public void testIsoRowSet_22() { + testIsoRowSet("(rowset (?x ?y ?z) (row (?x _:b0) (?y _:b1) (?z _:b0)) )", + "(rowset (?x ?y ?z) (row (?x _:c0) (?y _:c1) (?z _:c0)) )", + true); } + + @Test public void testIsoRowSet_23() { + testIsoRowSet("(rowset (?x ?y ?z) (row (?x _:b0) (?y _:b1) (?z _:b0)) )", + "(rowset (?x ?y ?z) (row (?x _:c0) (?y _:c1) (?z _:c2)) )", + false); } + + // Multiple rows + @Test public void testIsoRowSet_30() { + testIsoRowSet("(rowset (?x ?y) (row (?x 'A')) (row (?y 'B')) )", + "(rowset (?x ?y) (row (?y 'B')) (row (?x 'A')) )", + true); + } + + @Test public void testIsoRowSet_31() { + testIsoRowSet("(rowset (?x ?y) (row (?x _:b0)) (row (?y _:b0)) )", + "(rowset (?x ?y) (row (?x _:c0)) (row (?y _:c1)) )", + false); + } + + @Test public void testIsoRowSet_32() { + testIsoRowSet("(rowset (?x ?y) (row (?x _:b0)) (row (?y _:b0)) )", + "(rowset (?x ?y) (row (?y _:c1)) (row (?x _:c0)) )", + false); + } + + @Test public void testIsoRowSet_33() { + testIsoRowSet("(rowset (?x) (row (?x _:b0)) (row (?x _:b0)) )", + "(rowset (?x) (row (?x _:c0)) (row (?x _:c1)) )", + false); + } + + @Test public void testIsoRowSet_34() { + testIsoRowSet("(rowset (?x) (row (?x _:b0)) (row (?x _:b0)) )", + "(rowset (?x) (row (?x _:c0)) (row (?x _:c0)) )", + true); + } + + //ResultsCompare.equalsExact + + @Test public void testIsoExactRowSet_01() { + String x = "(rowset (?x) (row (?x _:b0)) )"; + // Re-parsed - fresh bnodes.s + testIsoExactRowSet(x, x, false); + } + + @Test public void testIsoExactRowSet_02() { + String x = """ + (rowset (?x ?y) + (row (?x _:b0) (?y _:b1)) + (row (?x _:b2) (?y _:b3)) + (row (?x _:b1) (?y _:b0)) + ) + """; + testIsoExactRowSet(x, x, false); + } + + @Test public void testIsoExactRowSet_10() { + + String x = """ + (rowset (?x ?y) + (row (?x _:b0) (?y _:b1)) + (row (?x _:b2) (?y _:b3)) + (row (?x _:b1) (?y _:b0)) + ) + """; + RowSetRewindable rowSet1 = SSE.parseRowSet(x).rewindable(); + RowSetRewindable rowSet2 =RowSetMem.create(rowSet1); + rowSet1.reset(); + rowSet2.reset(); + testIsoExactRowSet(rowSet1, x, rowSet2, x, true); + } + + @Test public void testIsoRowSet_35() { + String x = """ + (rowset (?x ?y) + (row (?x _:b0) (?y _:b1)) + (row (?x _:b2) (?y _:b3)) + (row (?x _:b1) (?y _:b0)) + ) + """; + testIsoRowSet(x, x, true); + } + + // Term testing + + @Test public void testIsoRowSet_40() { + testIsoRowSet("(rowset (?x) (row (?x <<(:s :p _:b)>>)) )", + "(rowset (?x) (row (?x <<(:s :p _:b)>>)) )", + true); + } + + @Test public void testIsoRowSet_41() { + testIsoRowSet("(rowset (?x ?y) (row (?x <<(:s :p _:b)>>) (?y <<(:s :p _:b)>>)) )", + "(rowset (?x ?y) (row (?x <<(:s :p _:b)>>) (?y <<(:s :p _:b)>>)) )", + true); + } + + @Test public void testIsoRowSet_42() { + testIsoRowSet("(rowset (?x ?y) (row (?x <<(:s :p _:b)>>) (?y <<(:s :p _:b)>>)) )", + "(rowset (?x ?y) (row (?x <<(:s :p _:b1)>>) (?y <<(:s :p _:b2)>>)) )", + false); + } + + @Test public void testIsoRowSet_50() { + testIsoRowSet("(rowset (?x) (row (?x <<(_:b :p <<(_:b :p _:b)>> )>>)) )", + "(rowset (?x) (row (?x <<(_:b :p <<(_:b :p _:b)>> )>>)) )", + true); + } + + @Test public void testIsoRowSet_51() { + testIsoRowSet("(rowset (?x) (row (?x <<(_:b :p <<(_:b :p _:b)>> )>>)) )", + "(rowset (?x) (row (?x <<(_:b :p <<(_:b1 :p _:b)>> )>>)) )", + false); + } + + // ---- Lists of rows. + @FunctionalInterface + interface ListTest { + boolean test(List list1, List list2); + } + + @Test public void testIsoList_01() { + testIsoListRows("(row (?x :x0) (?y :x1)) (row (?x :x2) (?y :x3)) ", + "(row (?x :x0) (?y :x1)) (row (?x :x2) (?y :x3)) ", + ResultsCompare::equalsExact, + true); + } + + @Test public void testIsoList_02() { + String arg1 = "(row (?x :x0) (?y :x1)) (row (?x :x2) (?y :x3))"; + String arg2 = "(row (?x :x2) (?y :x3)) (row (?x :x0) (?y :x1))"; + + testIsoListRows(arg1, arg2, ResultsCompare::equalsExact, true); + testIsoListRows(arg1, arg2, ResultsCompare::equalsExactAndOrder, false); + } + + // ---- Machinery + + private static void testIsoTerm(String str1, String str2, boolean expected) { + Node n1 = SSE.parseNode(str1); + Node n2 = SSE.parseNode(str2); + + testIsoTerm(n1, str1, n2, str2, expected); + testIsoTerm(n2, str2, n1, str1, expected); + + boolean b = equalsIsoByTerm(n1, n2); + if ( expected != b ) { + String msg = expected ? "(expected match)" : "(expected no match)"; + System.out.println("== ** BAD "+msg); + System.out.println("== Term1"); + System.out.println(" "+str1); + System.out.println("== Term2"); + System.out.println(" "+str2); + System.out.println(); + } + assertEquals(expected, b); + } + + private static void testIsoTerm(Node n2, String str1, Node n1, String str2, boolean expected) { + boolean b = equalsIsoByTerm(n1, n2); + if ( expected != b ) { + String msg = expected ? "(expected match)" : "(expected no match)"; + System.out.println("== ** BAD "+msg); + System.out.println("== Term1"); + System.out.println(" "+str1); + System.out.println("== Term2"); + System.out.println(" "+str2); + System.out.println(); + } + assertEquals(expected, b); + } + + private static boolean equalsIsoByTerm(Node n1, Node n2) { + IsoMapping mapping = IsoAlgRows.matchTermsTest(n1, n2, NodeUtils.sameNode); + return mapping != null; + } + + // RowSet testing. + + private static void testIsoRowSet(String str1, String str2, boolean expected) { + RowSetRewindable rowSet1 = SSE.parseRowSet(str1).rewindable(); + RowSetRewindable rowSet2 = SSE.parseRowSet(str2).rewindable(); + // Both ways round. + testIsoRowSet(rowSet1, str1, rowSet2, str2, expected); + rowSet1.reset(); + rowSet2.reset(); + testIsoRowSet(rowSet2, str2, rowSet1, str1, expected); + } + + private static void testIsoRowSet(RowSet rowSet1, String str1, RowSet rowSet2, String str2, boolean expected) { + RowSetRewindable rsw1 = rowSet1.rewindable(); + RowSetRewindable rsw2 = rowSet2.rewindable(); + boolean b = equalsIsoByTerm(rsw1, rsw2); + if ( expected != b ) { + System.out.println("== ** BAD"); + System.out.println("== rowSet1"); + System.out.println(str1); + System.out.println("== rowSet2"); + System.out.println(str2); + } + assertEquals(expected, b); + } + + private static boolean equalsIsoByTerm(RowSetRewindable rowSet1, RowSetRewindable rowSet2) { + return ResultsCompare.equalsByTerm(rowSet1, rowSet2); + } + + private void testIsoExactRowSet(String str1, String str2, boolean expected) { + RowSetRewindable rowSet1 = SSE.parseRowSet(str1).rewindable(); + RowSetRewindable rowSet2 = SSE.parseRowSet(str2).rewindable(); + // Both ways round. + testIsoExactRowSet(rowSet1, str1, rowSet2, str2, expected); + rowSet1.reset(); + rowSet2.reset(); + testIsoExactRowSet(rowSet2, str2, rowSet1, str1, expected); + } + + private void testIsoExactRowSet(RowSet rowSet1, String str1, RowSet rowSet2, String str2, boolean expected) { + RowSetRewindable rsw1 = rowSet1.rewindable(); + RowSetRewindable rsw2 = rowSet2.rewindable(); + EqualityTest eqtest = NodeUtils.sameRdfTerm; + boolean b = ResultsCompare.equalsExact(rowSet1, rowSet2); + if ( expected != b ) { + System.out.println("== ** BAD"); + System.out.println("== rowSet1"); + rsw1.reset(); + rsw1 = IsoLib.print(rsw1); + System.out.println("== rowSet2"); + rsw2.reset(); + rsw2 = IsoLib.print(rsw2); + } + assertEquals(expected, b); + } + + // Lists + + private static List parseRows(String str) { + RowSet rowSet = SSE.parseRowSet("(rowset () "+str+" )"); + Binding[] x = rowSet.stream().toArray(Binding[]::new); + return List.of(x); // Immutable, no nulls. + } + + private static void testIsoListRows(String str1, String str2, ListTest predicate, boolean expected) { + List rows1 = parseRows(str1); + List rows2 = parseRows(str2); + testIsoListRows(rows1, str1, rows2, str2, predicate, expected); + testIsoListRows(rows2, str2, rows1, str1, predicate, expected); + } + + private static void testIsoListRows(List rows1, String str1, List rows2, String str2, ListTest predicate, boolean expected) { + boolean b = predicate.test(rows1, rows2); + if ( expected != b ) { + String msg = expected ? "(expected match)" : "(expected no match)"; + System.out.println("== ** BAD "+msg); + System.out.println("== Row list 1"); + System.out.println(" "+str1); + System.out.println("== Row list 12"); + System.out.println(" "+str2); + System.out.println(); + } + assertEquals(expected, b); + } +} diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/util/TestIsoMatcher.java b/jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TestIsoMatcher.java similarity index 94% rename from jena-arq/src/test/java/org/apache/jena/sparql/util/TestIsoMatcher.java rename to jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TestIsoMatcher.java index 391ba8529d5..0d2ff1a9119 100644 --- a/jena-arq/src/test/java/org/apache/jena/sparql/util/TestIsoMatcher.java +++ b/jena-arq/src/test/java/org/apache/jena/sparql/util/iso/TestIsoMatcher.java @@ -16,8 +16,9 @@ * limitations under the License. */ -package org.apache.jena.sparql.util; +package org.apache.jena.sparql.util.iso; +import static org.apache.jena.atlas.lib.tuple.TupleFactory.tuple; import static org.junit.Assert.assertEquals; import java.util.ArrayList; @@ -25,15 +26,21 @@ import java.util.Collections; import java.util.List; +import org.junit.Test; + +import org.apache.jena.atlas.iterator.Iter; import org.apache.jena.atlas.lib.tuple.Tuple; import org.apache.jena.atlas.lib.tuple.TupleFactory; import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node; +import org.apache.jena.graph.Triple; import org.apache.jena.sparql.core.DatasetGraph; import org.apache.jena.sparql.sse.Item; import org.apache.jena.sparql.sse.SSE; import org.apache.jena.sparql.sse.builders.BuilderNode; -import org.junit.Test; +import org.apache.jena.sparql.util.IsoMatcher; +import org.apache.jena.sparql.util.NodeUtils; +import org.apache.jena.util.iterator.ExtendedIterator; public class TestIsoMatcher { @@ -336,10 +343,10 @@ private void testGraphVar(String s1, String s2, boolean result) { Graph g1 = SSE.parseGraph(s1); Graph g2 = SSE.parseGraph(s2); - Collection> x1 = IsoMatcher.tuplesTriples(g1.find()); - Collection> x2 = IsoMatcher.tuplesTriples(g2.find()); + Collection> x1 = tuplesTriples(g1.find()); + Collection> x2 = tuplesTriples(g2.find()); - boolean b = IsoAlg.isIsomorphic(x1, x2, Iso.mappableBlankNodesVariables, NodeUtils.sameRdfTerm); + boolean b = IsoAlgTuple.isIsomorphic(x1, x2, IsoLib.mappableBlankNodesVariables, NodeUtils.sameRdfTerm); if ( b != expected ) { System.out.println("===="); SSE.write(g1); @@ -371,4 +378,11 @@ private void testDSG(String s1, String s2, boolean iso) { } assertEquals(iso, b); } + + /*package*/ static List> tuplesTriples(ExtendedIterator iter) { + try { + return Iter.iter(iter).map(t->tuple(t.getSubject(), t.getPredicate(), t.getObject())).toList(); + } + finally { iter.close(); } + } } diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/ListUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/ListUtils.java index bde33c4d619..1eca2b51542 100644 --- a/jena-base/src/main/java/org/apache/jena/atlas/lib/ListUtils.java +++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/ListUtils.java @@ -87,9 +87,9 @@ public static boolean equalsUnordered(List list1, List list2) { List list2a = new ArrayList<>(list2); for ( T elt : list1 ) list2a.remove(elt); - if ( list2a.size() != 0 ) - return false; - return true; + if ( list2a.isEmpty() ) + return true; + return false; } /** diff --git a/jena-core/src/main/java/org/apache/jena/graph/Node.java b/jena-core/src/main/java/org/apache/jena/graph/Node.java index dd688836480..2f34f2ed71e 100644 --- a/jena-core/src/main/java/org/apache/jena/graph/Node.java +++ b/jena-core/src/main/java/org/apache/jena/graph/Node.java @@ -246,12 +246,15 @@ public boolean hasURI( String uri ) /*package*/ Node( ) {} /** - * Java rules for equals. See also {#sameTermAs} and {#sameValueAs} Nodes only equal - * other Nodes that have equal labels. + * Java rules for equals. See also {#sameTermAs} and {#sameValueAs}. + * Nodes only equal other Nodes that have equal labels. */ @Override public abstract boolean equals(Object o); + /** + * RDF term equality. + */ public boolean sameTermAs(Object o) { return equals( o ); } diff --git a/jena-extras/jena-serviceenhancer/src/test/java/org/apache/jena/sparql/service/enhancer/impl/TestServiceEnhancerCachedVsUncached.java b/jena-extras/jena-serviceenhancer/src/test/java/org/apache/jena/sparql/service/enhancer/impl/TestServiceEnhancerCachedVsUncached.java index 1e93278c63f..75589556071 100644 --- a/jena-extras/jena-serviceenhancer/src/test/java/org/apache/jena/sparql/service/enhancer/impl/TestServiceEnhancerCachedVsUncached.java +++ b/jena-extras/jena-serviceenhancer/src/test/java/org/apache/jena/sparql/service/enhancer/impl/TestServiceEnhancerCachedVsUncached.java @@ -25,24 +25,20 @@ import java.util.function.Consumer; import java.util.regex.Pattern; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + import org.apache.jena.atlas.logging.Log; -import org.apache.jena.query.Query; -import org.apache.jena.query.QueryExecution; -import org.apache.jena.query.QueryFactory; -import org.apache.jena.query.ResultSetFactory; -import org.apache.jena.query.ResultSetFormatter; -import org.apache.jena.query.ResultSetRewindable; +import org.apache.jena.query.*; import org.apache.jena.rdf.model.Model; import org.apache.jena.sparql.engine.iterator.QueryIterSlice; -import org.apache.jena.sparql.resultset.ResultSetCompare; +import org.apache.jena.sparql.resultset.ResultsCompare; import org.apache.jena.sparql.service.ServiceExecutorRegistry; import org.apache.jena.sparql.service.enhancer.init.ServiceEnhancerInit; import org.apache.jena.sparql.util.Context; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; /** @@ -90,7 +86,7 @@ public void test() { cxtMutator.accept(qeB.getContext()); rsB = ResultSetFactory.makeRewindable(qeB.execSelect()); - boolean isEqual = ResultSetCompare.equalsByValue(rsA, rsB); + boolean isEqual = ResultsCompare.equalsByValue(rsA, rsB); if (!isEqual) { rsA.reset(); ResultSetFormatter.out(System.out, rsA); diff --git a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestQuery.java b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestQuery.java index 60d4c392e3b..54f8e8db4a3 100644 --- a/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestQuery.java +++ b/jena-fuseki2/jena-fuseki-main/src/test/java/org/apache/jena/fuseki/main/TestQuery.java @@ -18,8 +18,9 @@ package org.apache.jena.fuseki.main; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.*; @@ -47,7 +48,7 @@ import org.apache.jena.sparql.engine.binding.Binding; import org.apache.jena.sparql.exec.QueryExec; import org.apache.jena.sparql.exec.http.*; -import org.apache.jena.sparql.resultset.ResultSetCompare; +import org.apache.jena.sparql.resultset.ResultsCompare; import org.apache.jena.sparql.sse.SSE; import org.apache.jena.sparql.util.Convert; @@ -316,7 +317,7 @@ private void execQuery(String queryString, int exceptedRowCount) { private void execQuery(String queryString, ResultSet expectedResultSet) { try ( QueryExecution qExec = QueryExecution.service(serviceQuery(), queryString) ) { ResultSet rs = qExec.execSelect(); - boolean b = ResultSetCompare.equalsByTerm(rs, expectedResultSet); + boolean b = ResultsCompare.equalsByTerm(rs, expectedResultSet); assertTrue(b, "Result sets different"); } } diff --git a/jena-integration-tests/src/test/java/org/apache/jena/test/service/TestCustomServiceExecutor.java b/jena-integration-tests/src/test/java/org/apache/jena/test/service/TestCustomServiceExecutor.java index c31e267ffb7..fb0d068fdcf 100644 --- a/jena-integration-tests/src/test/java/org/apache/jena/test/service/TestCustomServiceExecutor.java +++ b/jena-integration-tests/src/test/java/org/apache/jena/test/service/TestCustomServiceExecutor.java @@ -23,10 +23,13 @@ import java.util.function.Consumer; +import org.junit.Assert; +import org.junit.Test; + import org.apache.jena.atlas.logging.LogCtl; -import org.apache.jena.query.*; import org.apache.jena.graph.Node; import org.apache.jena.graph.NodeFactory; +import org.apache.jena.query.*; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.riot.ResultSetMgr; @@ -40,20 +43,20 @@ import org.apache.jena.sparql.engine.QueryIterator; import org.apache.jena.sparql.engine.binding.Binding; import org.apache.jena.sparql.exec.QueryExec; -import org.apache.jena.sparql.resultset.ResultSetCompare; +import org.apache.jena.sparql.resultset.ResultsCompare; import org.apache.jena.sparql.service.ServiceExec; import org.apache.jena.sparql.service.ServiceExecutorRegistry; import org.apache.jena.sparql.service.single.ServiceExecutor; import org.apache.jena.sparql.sse.SSE; -import org.junit.Assert; -import org.junit.Test; public class TestCustomServiceExecutor { static Table table = SSE.parseTable("(table (row (?s 1) (?p 2) (?o 3) ) )"); - /** A custom service factory that yields the above table for any request - * to urn:customService */ + /** + * A custom service factory that yields the above table + * for any request to urn:customService + */ static ServiceExecutor factory = (op, opOriginal, binding, execCxt) -> op.getService().getURI().equals("urn:customService") ? table.iterator(execCxt) @@ -250,7 +253,7 @@ public static void assertResult(String serviceIri, Consumer qePo public static void assertResult(String serviceIri, Consumer qePostProcessor, boolean withSilent) { ResultSetRewindable actual = runTestQuery(serviceIri, qePostProcessor, withSilent); - boolean isEqual = ResultSetCompare.equalsExact(actual, ResultSet.adapt(table.toRowSet())); + boolean isEqual = ResultsCompare.equalsExact(actual, ResultSet.adapt(table.toRowSet())); if (!isEqual) { actual.reset(); ResultSetMgr.write(System.err, actual, ResultSetLang.RS_Text); diff --git a/jena-tdb1/src/test/java/org/apache/jena/tdb1/solver/TestSolverTDB.java b/jena-tdb1/src/test/java/org/apache/jena/tdb1/solver/TestSolverTDB.java index d8c30237bc8..c3f4e444d75 100644 --- a/jena-tdb1/src/test/java/org/apache/jena/tdb1/solver/TestSolverTDB.java +++ b/jena-tdb1/src/test/java/org/apache/jena/tdb1/solver/TestSolverTDB.java @@ -24,10 +24,14 @@ import java.util.Iterator; import java.util.List; +import org.junit.BeforeClass; +import org.junit.Test; + 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.query.Dataset; +import org.apache.jena.query.ReadWrite; import org.apache.jena.riot.RDFDataMgr; import org.apache.jena.shared.PrefixMapping; import org.apache.jena.shared.impl.PrefixMappingImpl; @@ -40,12 +44,10 @@ import org.apache.jena.sparql.exec.RowSet; import org.apache.jena.sparql.exec.RowSetOps; import org.apache.jena.sparql.exec.RowSetRewindable; -import org.apache.jena.sparql.resultset.ResultSetCompare; +import org.apache.jena.sparql.resultset.ResultsCompare; import org.apache.jena.sparql.sse.SSE; import org.apache.jena.tdb1.ConfigTest; import org.apache.jena.tdb1.TDB1Factory; -import org.junit.BeforeClass; -import org.junit.Test; public class TestSolverTDB { static String graphData = null; @@ -131,7 +133,7 @@ private static void same(RowSet rs1, RowSet rs2, boolean result) { RowSetRewindable rsw1 = rs1.rewindable(); RowSetRewindable rsw2 = rs2.rewindable(); - boolean b = ResultSetCompare.equalsByValue(rsw1, rsw2); + boolean b = ResultsCompare.equalsByValue(rsw1, rsw2); if ( b != result ) { System.out.println("Different: "); rsw1.reset(); diff --git a/jena-tdb2/src/test/java/org/apache/jena/tdb2/solver/TestSolverTDB.java b/jena-tdb2/src/test/java/org/apache/jena/tdb2/solver/TestSolverTDB.java index 8ffc94c0f8a..1ffa2ef12a2 100644 --- a/jena-tdb2/src/test/java/org/apache/jena/tdb2/solver/TestSolverTDB.java +++ b/jena-tdb2/src/test/java/org/apache/jena/tdb2/solver/TestSolverTDB.java @@ -24,10 +24,15 @@ import java.util.Iterator; import java.util.List; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + 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.query.Dataset; +import org.apache.jena.query.ReadWrite; import org.apache.jena.riot.RDFDataMgr; import org.apache.jena.shared.PrefixMapping; import org.apache.jena.shared.impl.PrefixMappingImpl; @@ -40,13 +45,10 @@ import org.apache.jena.sparql.exec.RowSet; import org.apache.jena.sparql.exec.RowSetOps; import org.apache.jena.sparql.exec.RowSetRewindable; -import org.apache.jena.sparql.resultset.ResultSetCompare; +import org.apache.jena.sparql.resultset.ResultsCompare; import org.apache.jena.sparql.sse.SSE; import org.apache.jena.tdb2.ConfigTest; import org.apache.jena.tdb2.junit.TL; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; public class TestSolverTDB { static Dataset dataset = null; @@ -137,7 +139,7 @@ private static void same(RowSet rs1, RowSet rs2, boolean result) { RowSetRewindable rsw1 = rs1.rewindable(); RowSetRewindable rsw2 = rs2.rewindable(); - boolean b = ResultSetCompare.equalsByValue(rsw1, rsw2); + boolean b = ResultsCompare.equalsByValue(rsw1, rsw2); if ( b != result ) { System.out.println("Different: "); rsw1.reset();