diff --git a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/parameter/CollectionParameterValue.java b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/parameter/CollectionParameterValue.java index 092b1fc3b..5e5042bb7 100644 --- a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/parameter/CollectionParameterValue.java +++ b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/parameter/CollectionParameterValue.java @@ -17,6 +17,9 @@ */ package cz.cvut.kbss.jopa.query.parameter; +import cz.cvut.kbss.jopa.query.sparql.SparqlConstants; + +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -29,7 +32,7 @@ class CollectionParameterValue extends AbstractParameterValue { } @Override - public Object getValue() { + public List getValue() { return values.stream().map(ParameterValue::getValue).collect(Collectors.toList()); } @@ -37,4 +40,22 @@ public Object getValue() { public String getQueryString() { return values.stream().map(ParameterValue::getQueryString).collect(Collectors.joining(",")); } + + @Override + public List toQueryValues(int size) { + assert size >= values.size(); + final List result = new ArrayList<>(size); + values.stream().map(ParameterValue::getQueryString).forEach(result::add); + if (values.size() < size) { + for (int i = values.size(); i < size; i++) { + result.add(SparqlConstants.UNDEF); + } + } + return result; + } + + @Override + public int valueCount() { + return values.size(); + } } diff --git a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/parameter/ParameterValue.java b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/parameter/ParameterValue.java index 3864bd96d..7cd5ad4b8 100644 --- a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/parameter/ParameterValue.java +++ b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/parameter/ParameterValue.java @@ -17,6 +17,11 @@ */ package cz.cvut.kbss.jopa.query.parameter; +import cz.cvut.kbss.jopa.query.sparql.SparqlConstants; + +import java.util.ArrayList; +import java.util.List; + /** * Query parameter value holder. */ @@ -36,6 +41,31 @@ public interface ParameterValue { */ String getQueryString(); + /** + * Builds a list of the specified size containing the value(s) represented by this parameter value. + *

+ * If this instance does not contain enough values to fill in the list of the specified size, its remainder is + * filled with {@link cz.cvut.kbss.jopa.query.sparql.SparqlConstants#UNDEF}s. + *

+ * The resulting list will be used to build a SPARQL {@literal VALUES} table. + * + * @param size Requested size of value list + * @return List of values + */ + default List toQueryValues(int size) { + assert size > 0; + + if (size == 1) { + return List.of(getQueryString()); + } + final List result = new ArrayList<>(size); + result.add(getQueryString()); + for (int i = 1; i < size; i++) { + result.add(SparqlConstants.UNDEF); + } + return result; + } + /** * Whether this parameter value is set or it represents just the parameter identification. * @@ -44,4 +74,13 @@ public interface ParameterValue { default boolean isSet() { return true; } + + /** + * Returns the number of values held by this instance. + *

+ * Will return number different from 1 only for collection value parameters. + * + * @return Number of values represented by this instance + */ + default int valueCount() {return 1;} } diff --git a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/sparql/SparqlConstants.java b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/sparql/SparqlConstants.java index 14dabad48..b965bff89 100644 --- a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/sparql/SparqlConstants.java +++ b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/sparql/SparqlConstants.java @@ -37,6 +37,11 @@ public class SparqlConstants { */ public static final String RDF_TYPE_SHORTCUT = "a"; + /** + * The {@literal UNDEF} keyword. + */ + public static final String UNDEF = "UNDEF"; + private SparqlConstants() { throw new AssertionError(); } diff --git a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/sparql/SparqlQueryHolder.java b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/sparql/SparqlQueryHolder.java index 5a6690a65..69393345b 100644 --- a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/sparql/SparqlQueryHolder.java +++ b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/sparql/SparqlQueryHolder.java @@ -21,7 +21,15 @@ import cz.cvut.kbss.jopa.query.QueryHolder; import cz.cvut.kbss.jopa.query.QueryParameter; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; public class SparqlQueryHolder implements QueryHolder { @@ -193,15 +201,32 @@ private static Optional assembleValuesClause(Set> para return Optional.empty(); } final StringBuilder variables = new StringBuilder(); - final StringBuilder data = new StringBuilder(); + final int tableSize = maxValueCount(parameters); + final List> valueTable = new ArrayList<>(parameters.size()); for (QueryParameter qp : parameters) { if (!variables.isEmpty()) { variables.append(' '); } variables.append(qp.getIdentifierAsQueryString()); - data.append('(').append(qp.getValue().getQueryString()).append(')'); + valueTable.add(qp.getValue().toQueryValues(tableSize)); } - return Optional.of(" VALUES (" + variables + ") {" + data + "}"); + return Optional.of(" VALUES (" + variables + ") { " + valueTableToString(valueTable, tableSize) + "}"); + } + + private static int maxValueCount(Set> parameters) { + return parameters.stream().map(p -> p.getValue().valueCount()).max(Integer::compareTo).orElse(1); + } + + private static String valueTableToString(List> valueTable, int rowSize) { + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < rowSize; i++) { + sb.append("( "); + for (List row : valueTable) { + sb.append(row.get(i)).append(" "); + } + sb.append(") "); + } + return sb.toString(); } @Override diff --git a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/parameter/CollectionParameterValueTest.java b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/parameter/CollectionParameterValueTest.java index 938e7d4cf..d6a40619d 100644 --- a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/parameter/CollectionParameterValueTest.java +++ b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/parameter/CollectionParameterValueTest.java @@ -18,12 +18,16 @@ package cz.cvut.kbss.jopa.query.parameter; import cz.cvut.kbss.jopa.environment.utils.Generators; +import cz.cvut.kbss.jopa.query.sparql.SparqlConstants; import org.junit.jupiter.api.Test; import java.util.Arrays; +import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItems; import static org.junit.jupiter.api.Assertions.assertEquals; class CollectionParameterValueTest { @@ -34,17 +38,35 @@ class CollectionParameterValueTest { @Test void getValueReturnsValuesOfIndividualElements() { - final CollectionParameterValue sut = new CollectionParameterValue(Arrays.asList(V_ONE, V_TWO, V_THREE)); + final CollectionParameterValue sut = new CollectionParameterValue(List.of(V_ONE, V_TWO, V_THREE)); - assertEquals(Arrays.asList(V_ONE.getValue(), V_TWO.getValue(), V_THREE.getValue()), sut.getValue()); + assertEquals(List.of(V_ONE.getValue(), V_TWO.getValue(), V_THREE.getValue()), sut.getValue()); } @Test void getQueryStringReturnsQueryStringRepresentationsOfIndividualElementsJoinedByComma() { - final CollectionParameterValue sut = new CollectionParameterValue(Arrays.asList(V_ONE, V_TWO, V_THREE)); + final CollectionParameterValue sut = new CollectionParameterValue(List.of(V_ONE, V_TWO, V_THREE)); assertEquals( Stream.of(V_ONE, V_TWO, V_THREE).map(ParameterValue::getQueryString).collect(Collectors.joining(",")), sut.getQueryString()); } + + @Test + void toQueryValuesReturnsListOfQueryStringifiedParameterValues() { + final CollectionParameterValue sut = new CollectionParameterValue(List.of(V_ONE, V_TWO, V_THREE)); + final List result = sut.toQueryValues(sut.valueCount()); + assertEquals(Stream.of(V_ONE, V_TWO, V_THREE).map(ParameterValue::getQueryString).toList(), result); + } + + @Test + void toQueryValuesReturnsListOfQueryStringifiedParameterValuesFilledWithSparqlUndefWhenSizeIsGreaterThanValueCount() { + final int size = 6; + final CollectionParameterValue sut = new CollectionParameterValue(List.of(V_ONE, V_TWO, V_THREE)); + final List result = sut.toQueryValues(size); + assertThat(result, hasItems(Stream.of(V_ONE, V_TWO, V_THREE).map(ParameterValue::getQueryString).toArray(String[]::new))); + final String[] remainder = new String[size - sut.valueCount()]; + Arrays.fill(remainder, SparqlConstants.UNDEF); + assertThat(result, hasItems(remainder)); + } } diff --git a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/parameter/ParameterValueTest.java b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/parameter/ParameterValueTest.java new file mode 100644 index 000000000..9d0222bb1 --- /dev/null +++ b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/parameter/ParameterValueTest.java @@ -0,0 +1,29 @@ +package cz.cvut.kbss.jopa.query.parameter; + +import cz.cvut.kbss.jopa.environment.utils.Generators; +import cz.cvut.kbss.jopa.query.sparql.SparqlConstants; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class ParameterValueTest { + + @Test + void toQueryValuesReturnsListOfSizeOneWithParameterValueStringifiedForQuery() { + final ParameterValue sut = new IntegerParameterValue(Generators.randomPositiveInt(1000)); + final List result = sut.toQueryValues(1); + assertEquals(List.of(sut.getQueryString()), result); + } + + @Test + void toQueryValuesReturnsListOfSpecifiedSizeFilledWithValueAndUndef() { + final ParameterValue sut = new IntegerParameterValue(Generators.randomPositiveInt(1000)); + int size = 5; + final List result = sut.toQueryValues(size); + assertEquals(size, result.size()); + assertEquals(sut.getQueryString(), result.get(0)); + result.subList(1, size).forEach(v -> assertEquals(SparqlConstants.UNDEF, v)); + } +} diff --git a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/sparql/NamedParameterSparqlQueryHolderTest.java b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/sparql/NamedParameterSparqlQueryHolderTest.java index 95d4b7200..96a74677e 100644 --- a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/sparql/NamedParameterSparqlQueryHolderTest.java +++ b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/sparql/NamedParameterSparqlQueryHolderTest.java @@ -36,14 +36,15 @@ public class NamedParameterSparqlQueryHolderTest { - private static final String QUERY = "PREFIX foaf: \n" + - "SELECT ?craft\n" + - "{\n" + - "?craft foaf:name \"Apollo 7\" .\n" + - "?craft foaf:homepage ?homepage .\n" + - "}"; + private static final String QUERY = """ + PREFIX foaf: + SELECT ?craft + { + ?craft foaf:name "Apollo 7" . + ?craft foaf:homepage ?homepage . + }"""; private static final List PARTS = Arrays.asList("PREFIX foaf: \n" + - "SELECT ", "\n{\n", " foaf:name \"Apollo 7\" .\n", " foaf:homepage ", " .\n}"); + "SELECT ", "\n{\n ", " foaf:name \"Apollo 7\" .\n ", " foaf:homepage ", " .\n}"); private static final List PARAMS = Arrays.asList("craft", "craft", "craft", "homepage"); private static final Set PARAM_NAMES = new HashSet<>(Arrays.asList("craft", "homepage")); @@ -103,7 +104,7 @@ public void getValueOfUnknownParameterThrowsIllegalArgumentException() { @Test public void testSetParameter() { - final String value = "http://kbss.felk.cvut.cz"; + final String value = "https://kbss.felk.cvut.cz"; holder.setParameter(new QueryParameter<>("homepage", paramValueFactory), value); assertEquals(value, holder.getParameterValue(holder.getParameter("homepage"))); } @@ -128,7 +129,7 @@ public void setUnknownParameterThrowsException() { @Test public void clearParameterRemovesParameterValue() { final QueryParameter qp = new QueryParameter<>("homepage", paramValueFactory); - holder.setParameter(qp, URI.create("http://kbss.felk.cvut.cz")); + holder.setParameter(qp, URI.create("https://kbss.felk.cvut.cz")); assertNotNull(holder.getParameterValue(qp)); holder.clearParameter(qp); assertNull(holder.getParameterValue(qp)); @@ -137,7 +138,7 @@ public void clearParameterRemovesParameterValue() { @Test public void clearParametersRemovesAllParameterValues() { final QueryParameter qp = new QueryParameter<>("homepage", paramValueFactory); - holder.setParameter(qp, URI.create("http://kbss.felk.cvut.cz")); + holder.setParameter(qp, URI.create("https://kbss.felk.cvut.cz")); final QueryParameter qpTwo = new QueryParameter<>("craft", paramValueFactory); holder.setParameter(qpTwo, "Programming"); holder.getParameters().forEach(param -> assertNotNull(holder.getParameterValue(param))); @@ -148,26 +149,28 @@ public void clearParametersRemovesAllParameterValues() { @Test public void assembleQueryWithUri() { final QueryParameter qp = new QueryParameter<>("homepage", paramValueFactory); - holder.setParameter(qp, URI.create("http://kbss.felk.cvut.cz")); - final String expected = "PREFIX foaf: \n" + - "SELECT ?craft\n" + - "{\n" + - "?craft foaf:name \"Apollo 7\" .\n" + - "?craft foaf:homepage .\n" + - "}"; + holder.setParameter(qp, URI.create("https://kbss.felk.cvut.cz")); + final String expected = """ + PREFIX foaf: + SELECT ?craft + { + ?craft foaf:name "Apollo 7" . + ?craft foaf:homepage . + }"""; assertEquals(expected, holder.assembleQuery()); } @Test public void assembleQueryWithLiteral() { final QueryParameter qp = new QueryParameter<>("homepage", paramValueFactory); - holder.setParameter(qp, "http://kbss.felk.cvut.cz", null); - final String expected = "PREFIX foaf: \n" + - "SELECT ?craft\n" + - "{\n" + - "?craft foaf:name \"Apollo 7\" .\n" + - "?craft foaf:homepage \"http://kbss.felk.cvut.cz\" .\n" + - "}"; + holder.setParameter(qp, "https://kbss.felk.cvut.cz", null); + final String expected = """ + PREFIX foaf: + SELECT ?craft + { + ?craft foaf:name "Apollo 7" . + ?craft foaf:homepage "https://kbss.felk.cvut.cz" . + }"""; assertEquals(expected, holder.assembleQuery()); } @@ -192,10 +195,10 @@ public void setParametersAndAssembleQueryWithMultipleParamsNextToEachOther() { void setParameterAddsValuesClauseWhenSetParameterIsInProjection() { final QueryParameter qp = new QueryParameter<>("craft", paramValueFactory); qp.setProjected(true); - holder.setParameter(qp, URI.create("http://kbss.felk.cvut.cz/apollo7")); + holder.setParameter(qp, URI.create("https://kbss.felk.cvut.cz/apollo7")); final String result = holder.assembleQuery(); - assertThat(result, endsWith("VALUES (?craft) {(" + holder.getParameter("craft").getValue() - .getQueryString() + ")}")); + assertThat(result, endsWith("VALUES (?craft) { ( " + holder.getParameter("craft").getValue() + .getQueryString() + " ) }")); assertThat(result, containsString(QUERY)); } } diff --git a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/sparql/SparqlQueryHolderTest.java b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/sparql/SparqlQueryHolderTest.java index f4e4db00e..31a28ccb6 100644 --- a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/sparql/SparqlQueryHolderTest.java +++ b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/sparql/SparqlQueryHolderTest.java @@ -17,34 +17,40 @@ */ package cz.cvut.kbss.jopa.query.sparql; +import cz.cvut.kbss.jopa.environment.utils.Generators; import cz.cvut.kbss.jopa.query.QueryParameter; import cz.cvut.kbss.jopa.query.parameter.ParameterValueFactory; import cz.cvut.kbss.jopa.sessions.MetamodelProvider; +import cz.cvut.kbss.jopa.utils.IdentifierTransformer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.util.Arrays; +import java.net.URI; +import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; -import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.endsWith; +import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; class SparqlQueryHolderTest { private static final String QUERY = "SELECT ?x WHERE { ?x a ?type . }"; - private static final List PARTS = Arrays.asList("SELECT ", " WHERE { ", " a ", " . }"); - private static final List PARAMS = Arrays.asList("x", "x", "type"); private SparqlQueryHolder sut; @BeforeEach void setUp() { - this.sut = new SparqlQueryHolder(QUERY, PARTS, - PARAMS.stream() - .map(name -> new QueryParameter<>(name, new ParameterValueFactory(mock(MetamodelProvider.class)))) - .collect(Collectors.toList())); + final List> queryParams = new ArrayList<>(); + final ParameterValueFactory parameterValueFactory = new ParameterValueFactory(mock(MetamodelProvider.class)); + final QueryParameter xParam = new QueryParameter<>("x", parameterValueFactory); + xParam.setProjected(true); + queryParams.add(xParam); + queryParams.add(xParam); + queryParams.add(new QueryParameter<>("type", parameterValueFactory)); + this.sut = new SparqlQueryHolder(QUERY, List.of("SELECT ", " WHERE { ", " a ", " . }"), queryParams); } @Test @@ -81,4 +87,39 @@ void setFirstResultAndSetMaxResultsAddsLimitAndOffsetToAssembledQuery() { assertThat(result, containsString("LIMIT 10")); assertThat(result, containsString("OFFSET 5")); } + + @Test + void assembleQuerySupportsPluralValues() { + final List paramValues = List.of(Generators.createIndividualIdentifier(), Generators.createIndividualIdentifier()); + sut.setParameter(sut.getParameter("x"), paramValues); + final String result = sut.assembleQuery(); + assertThat(result, containsString("VALUES (?x)")); + paramValues.forEach(v -> assertThat(result, containsString(" ( " + IdentifierTransformer.stringifyIri(v) + " )"))); + } + + @Test + void assembleQuerySupportsValuesWithInEqualSize() { + final List> queryParams = new ArrayList<>(); + final ParameterValueFactory parameterValueFactory = new ParameterValueFactory(mock(MetamodelProvider.class)); + final QueryParameter xParam = new QueryParameter<>("x", parameterValueFactory); + xParam.setProjected(true); + queryParams.add(xParam); + final QueryParameter typeParam = new QueryParameter<>("type", parameterValueFactory); + typeParam.setProjected(true); + queryParams.add(typeParam); + queryParams.add(xParam); + queryParams.add(typeParam); + this.sut = new SparqlQueryHolder(QUERY, List.of("SELECT ", ", ", " WHERE { ", " a ", " . }"), queryParams); + final List xValues = List.of(Generators.createIndividualIdentifier(), Generators.createIndividualIdentifier()); + final List typeValues = List.of(Generators.createIndividualIdentifier(), Generators.createIndividualIdentifier(), Generators.createIndividualIdentifier()); + sut.setParameter(sut.getParameter("x"), xValues); + sut.setParameter(sut.getParameter("type"), typeValues); + + final String result = sut.assembleQuery(); + assertThat(result, containsString("VALUES (?x ?type)")); + assertThat(result, containsString("( " + IdentifierTransformer.stringifyIri(xValues.get(0)) + " " + IdentifierTransformer.stringifyIri(typeValues.get(0)) + " )")); + assertThat(result, containsString("( " + IdentifierTransformer.stringifyIri(xValues.get(1)) + " " + IdentifierTransformer.stringifyIri(typeValues.get(1)) + " )")); + typeValues.subList(2, typeValues.size()) + .forEach(v -> assertThat(result, containsString(" ( UNDEF " + IdentifierTransformer.stringifyIri(v) + " )"))); + } } diff --git a/jopa-integration-tests/src/main/java/cz/cvut/kbss/jopa/test/query/runner/QueryRunner.java b/jopa-integration-tests/src/main/java/cz/cvut/kbss/jopa/test/query/runner/QueryRunner.java index 66f0754b2..806668e78 100644 --- a/jopa-integration-tests/src/main/java/cz/cvut/kbss/jopa/test/query/runner/QueryRunner.java +++ b/jopa-integration-tests/src/main/java/cz/cvut/kbss/jopa/test/query/runner/QueryRunner.java @@ -236,13 +236,13 @@ void testCreateNamedNativeQueryWithParameterSetting() { @Test void queryWithMappingReturnsResultWithVariablesMappedAccordingly() { final List res = getEntityManager().createNativeQuery("SELECT * WHERE {" + - "?x a <" + Vocabulary.C_OWL_CLASS_A + "> ;" + - "<" + Vocabulary.P_A_STRING_ATTRIBUTE + "> ?y ." + - "}", OWLClassA.VARIABLE_MAPPING).getResultList(); + "?x a <" + Vocabulary.C_OWL_CLASS_A + "> ;" + + "<" + Vocabulary.P_A_STRING_ATTRIBUTE + "> ?y ." + + "}", OWLClassA.VARIABLE_MAPPING).getResultList(); final Map expected = new HashMap<>(); QueryTestEnvironment.getData(OWLClassA.class) .forEach(a -> expected.put(a.getUri().toString(), - new LangString(a.getStringAttribute(), "en"))); + new LangString(a.getStringAttribute(), "en"))); assertEquals(expected.size(), res.size()); for (Object row : res) { assertInstanceOf(Object[].class, row); @@ -256,9 +256,9 @@ void queryWithMappingReturnsResultWithVariablesMappedAccordingly() { @Test void queryWithConstructorMappingReturnsCorrectInstances() { final List res = getEntityManager().createNativeQuery("SELECT * WHERE {" + - "?x a <" + Vocabulary.C_OWL_CLASS_A + "> ;" + - "<" + Vocabulary.P_A_STRING_ATTRIBUTE + "> ?y ." + - "}", OWLClassA.CONSTRUCTOR_MAPPING) + "?x a <" + Vocabulary.C_OWL_CLASS_A + "> ;" + + "<" + Vocabulary.P_A_STRING_ATTRIBUTE + "> ?y ." + + "}", OWLClassA.CONSTRUCTOR_MAPPING) .getResultList(); final Map expected = new HashMap<>(); QueryTestEnvironment.getData(OWLClassA.class).forEach(a -> expected.put(a.getUri(), a)); @@ -278,9 +278,9 @@ private void verifyOWLClassAInstances(List res, Map expected) { @Test void queryWithEntityMappingReturnsCorrectManagedInstances() { final List res = getEntityManager().createNativeQuery("SELECT * WHERE {" + - "?x a <" + Vocabulary.C_OWL_CLASS_A + "> ;" + - "<" + Vocabulary.P_A_STRING_ATTRIBUTE + "> ?stringAttribute ." + - "}", OWLClassA.ENTITY_MAPPING).getResultList(); + "?x a <" + Vocabulary.C_OWL_CLASS_A + "> ;" + + "<" + Vocabulary.P_A_STRING_ATTRIBUTE + "> ?stringAttribute ." + + "}", OWLClassA.ENTITY_MAPPING).getResultList(); final Map expected = new HashMap<>(); QueryTestEnvironment.getData(OWLClassA.class).forEach(a -> expected.put(a.getUri(), a)); @@ -293,8 +293,8 @@ void queryWithEntityMappingReturnsCorrectManagedInstances() { @Test void queryWithEntityMappingLoadsReferencedEntitiesAsWell() { final List res = getEntityManager().createNativeQuery("SELECT ?x ?y WHERE {" + - "?x a ?dType ;" + - "?hasA ?y . }", OWLClassD.MAPPING_NAME) + "?x a ?dType ;" + + "?hasA ?y . }", OWLClassD.MAPPING_NAME) .setParameter("dType", URI.create(Vocabulary.C_OWL_CLASS_D)) .setParameter("hasA", URI.create(Vocabulary.P_HAS_OWL_CLASS_A)) .getResultList(); @@ -328,12 +328,12 @@ private void verifyOwlClassAInstance(OWLClassA expected, OWLClassA actual) { @Test public void queryWithEntityMappingLoadsReferencedEntityAndInheritedAttributes() { final List res = getEntityManager().createNativeQuery("SELECT * WHERE {" + - "?x a ?type ;" + - "?hasA ?y ;" + - "?rdfsLabel ?label ;" + - "?hasDescription ?description ;" + - "?hasInt ?intAttribute ." + - "}", OWLClassT.MAPPING_NAME) + "?x a ?type ;" + + "?hasA ?y ;" + + "?rdfsLabel ?label ;" + + "?hasDescription ?description ;" + + "?hasInt ?intAttribute ." + + "}", OWLClassT.MAPPING_NAME) .setParameter("type", URI.create(Vocabulary.C_OWL_CLASS_T)) .setParameter("hasA", URI.create(Vocabulary.P_HAS_OWL_CLASS_A)) .setParameter("rdfsLabel", URI.create(RDFS.LABEL)) @@ -442,8 +442,8 @@ void selectionByObjectPropertySupportsEntityAsQueryParameter() { public void selectTypesWithDisableInferenceQueryHintReturnsOnlyAssertedTypes() throws Exception { final String superType = Vocabulary.CLASS_IRI_BASE + "A-superclass"; persistTestData(Collections.singleton( - new Quad(URI.create(Vocabulary.C_OWL_CLASS_A), URI.create(RDFS.SUB_CLASS_OF), URI.create(superType))), - getEntityManager()); + new Quad(URI.create(Vocabulary.C_OWL_CLASS_A), URI.create(RDFS.SUB_CLASS_OF), URI.create(superType))), + getEntityManager()); final OWLClassA a = QueryTestEnvironment.getData(OWLClassA.class).get(0); final Set types = new HashSet<>(a.getTypes()); types.add(a.getClass().getAnnotation(OWLClass.class).iri()); @@ -462,7 +462,7 @@ public void setParameterSupportsLangStringValue() { final List aInstances = QueryTestEnvironment.getData(OWLClassA.class); final List matching = aInstances.subList(0, Generators.randomPositiveInt(3, aInstances.size())); final Set params = matching.stream().map(a -> new LangString(a.getStringAttribute(), - TestEnvironment.PERSISTENCE_LANGUAGE)) + TestEnvironment.PERSISTENCE_LANGUAGE)) .collect(Collectors.toSet()); final EntityManager em = getEntityManager(); final String query = "SELECT ?x WHERE { ?x ?stringAtt ?value . FILTER (?value IN (?params)) }"; @@ -473,4 +473,17 @@ public void setParameterSupportsLangStringValue() { assertEquals(matching.size(), result.size()); matching.forEach(a -> assertThat((List) result, hasItem(a.getUri()))); } + + @Test + protected void querySupportsPluralValuesParameter() { + final OWLClassA entityA = Generators.getRandomItem(QueryTestEnvironment.getData(OWLClassA.class)); + final OWLClassB entityB = Generators.getRandomItem(QueryTestEnvironment.getData(OWLClassB.class)); + final List result = getEntityManager().createNativeQuery("SELECT ?x ?type WHERE { ?x a ?type . }") + .setParameter("x", List.of(entityA.getUri(), entityB.getUri())) + .getResultList(); + assertThat((List) result, hasItem(new URI[]{entityA.getUri(), URI.create(Vocabulary.C_OWL_CLASS_A)})); + entityA.getTypes() + .forEach(t -> assertThat((List) result, hasItem(new URI[]{entityA.getUri(), URI.create(t)}))); + assertThat((List) result, hasItem(new URI[]{entityB.getUri(), URI.create(Vocabulary.C_OWL_CLASS_B)})); + } } diff --git a/jopa-integration-tests/src/main/java/cz/cvut/kbss/jopa/test/query/runner/TypedQueryRunner.java b/jopa-integration-tests/src/main/java/cz/cvut/kbss/jopa/test/query/runner/TypedQueryRunner.java index 65abc92bb..d2680d0ad 100644 --- a/jopa-integration-tests/src/main/java/cz/cvut/kbss/jopa/test/query/runner/TypedQueryRunner.java +++ b/jopa-integration-tests/src/main/java/cz/cvut/kbss/jopa/test/query/runner/TypedQueryRunner.java @@ -24,7 +24,12 @@ import cz.cvut.kbss.jopa.model.descriptors.EntityDescriptor; import cz.cvut.kbss.jopa.model.query.TypedQuery; import cz.cvut.kbss.jopa.query.QueryHints; -import cz.cvut.kbss.jopa.test.*; +import cz.cvut.kbss.jopa.test.OWLClassA; +import cz.cvut.kbss.jopa.test.OWLClassB; +import cz.cvut.kbss.jopa.test.OWLClassD; +import cz.cvut.kbss.jopa.test.OWLClassE; +import cz.cvut.kbss.jopa.test.OWLClassM; +import cz.cvut.kbss.jopa.test.Vocabulary; import cz.cvut.kbss.jopa.test.environment.DataAccessor; import cz.cvut.kbss.jopa.test.environment.Generators; import cz.cvut.kbss.jopa.test.query.QueryTestEnvironment; @@ -37,11 +42,20 @@ import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.temporal.ChronoUnit; -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; -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.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; public abstract class TypedQueryRunner extends BaseQueryRunner {