diff --git a/core/model-api/src/main/java/org/eclipse/rdf4j/model/ValueFactory.java b/core/model-api/src/main/java/org/eclipse/rdf4j/model/ValueFactory.java
index 183292d241a..a1bacd16b41 100644
--- a/core/model-api/src/main/java/org/eclipse/rdf4j/model/ValueFactory.java
+++ b/core/model-api/src/main/java/org/eclipse/rdf4j/model/ValueFactory.java
@@ -100,6 +100,16 @@ public interface ValueFactory {
*/
Literal createLiteral(String label, CoreDatatype datatype);
+ /**
+ * Creates a new literal with the supplied label and datatype.
+ *
+ * @param label The literal's label, must not be null.
+ * @param datatype The literal's datatype. If it is null, the datatype
+ * {@code xsd:string} will be assigned to this
+ * literal.
+ */
+ Literal createLiteral(String label, IRI datatype, CoreDatatype coreDatatype);
+
/**
* Creates a new xsd:boolean-typed literal representing the specified value.
*
diff --git a/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/AbstractLiteral.java b/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/AbstractLiteral.java
index e9f7a113330..f8c16a70bcf 100644
--- a/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/AbstractLiteral.java
+++ b/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/AbstractLiteral.java
@@ -236,6 +236,16 @@ static class TypedLiteral extends AbstractLiteral {
this.datatype = datatype.getIri();
}
+ TypedLiteral(String label, IRI datatype, CoreDatatype coreDatatype) {
+ assert datatype != null;
+ assert coreDatatype != null;
+ assert coreDatatype == CoreDatatype.NONE || datatype == coreDatatype.getIri();
+
+ this.label = label;
+ this.datatype = datatype;
+ this.coreDatatype = coreDatatype;
+ }
+
@Override
public String getLabel() {
return label;
@@ -379,7 +389,7 @@ private static String toString(double value) {
protected Number value;
private final String label;
- private final CoreDatatype datatype;
+ private final CoreDatatype.XSD datatype;
NumberLiteral(byte value) {
this(value, Byte.toString(value), CoreDatatype.XSD.BYTE);
@@ -405,7 +415,7 @@ private static String toString(double value) {
this(value, toString(value), CoreDatatype.XSD.DOUBLE);
}
- NumberLiteral(Number value, String label, CoreDatatype datatype) {
+ NumberLiteral(Number value, String label, CoreDatatype.XSD datatype) {
this.value = value;
this.label = label;
this.datatype = datatype;
@@ -585,7 +595,7 @@ static class TemporalAccessorLiteral extends AbstractLiteral {
.toFormatter();
- private static final Map DATATYPES = datatypes();
+ private static final Map DATATYPES = datatypes();
private static final Map FORMATTERS = formatters();
static TemporalAccessor parseTemporalAccessor(String label) throws DateTimeException {
@@ -601,14 +611,14 @@ static TemporalAccessor parseTemporalAccessor(String label) throws DateTimeExcep
return value;
}
- private static Map datatypes() {
+ private static Map datatypes() {
int date = key(YEAR, MONTH_OF_YEAR, DAY_OF_MONTH);
int time = key(HOUR_OF_DAY, MINUTE_OF_HOUR, SECOND_OF_MINUTE);
int nano = key(NANO_OF_SECOND);
int zone = key(OFFSET_SECONDS);
- Map datatypes = new HashMap<>();
+ Map datatypes = new HashMap<>();
datatypes.put(date + time, CoreDatatype.XSD.DATETIME);
datatypes.put(date + time + nano, CoreDatatype.XSD.DATETIME);
@@ -689,7 +699,7 @@ private static int key(Predicate include, ChronoField... fields) {
private final TemporalAccessor value;
private final String label;
- private final CoreDatatype datatype;
+ private final CoreDatatype.XSD datatype;
TemporalAccessorLiteral(TemporalAccessor value) {
diff --git a/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/AbstractValueFactory.java b/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/AbstractValueFactory.java
index 9938c299e77..b75ecf02d99 100644
--- a/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/AbstractValueFactory.java
+++ b/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/AbstractValueFactory.java
@@ -128,6 +128,19 @@ public Literal createLiteral(String label, CoreDatatype datatype) {
return new TypedLiteral(label, datatype);
}
+ @Override
+ public Literal createLiteral(String label, IRI datatype, CoreDatatype coreDatatype) {
+ Objects.requireNonNull(label, "Label may not be null");
+ Objects.requireNonNull(datatype, "Datatype may not be null");
+ Objects.requireNonNull(coreDatatype, "CoreDatatype may not be null");
+
+ if (reserved(coreDatatype)) {
+ throw new IllegalArgumentException("reserved datatype <" + datatype + ">");
+ }
+
+ return new TypedLiteral(label, datatype, coreDatatype);
+ }
+
@Override
public Literal createLiteral(String label, String language) {
diff --git a/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/CoreDatatype.java b/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/CoreDatatype.java
index 497e49b09e5..c37230a4bd6 100644
--- a/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/CoreDatatype.java
+++ b/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/CoreDatatype.java
@@ -263,10 +263,17 @@ public Optional asXSDDatatype() {
return optional;
}
+ @Override
+ public String toString() {
+ return iri.toString();
+ }
+
}
enum RDF implements CoreDatatype {
+ HTML(iri("HTML")),
+ XMLLITERAL(iri("XMLLiteral")),
LANGSTRING(iri("langString"));
public static final String NAMESPACE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
@@ -299,6 +306,11 @@ public Optional asRDFDatatype() {
return optional;
}
+ @Override
+ public String toString() {
+ return iri.toString();
+ }
+
}
enum GEO implements CoreDatatype {
@@ -335,6 +347,10 @@ public Optional asGEODatatype() {
return optional;
}
+ @Override
+ public String toString() {
+ return iri.toString();
+ }
}
}
diff --git a/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/CoreDatatypeHelper.java b/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/CoreDatatypeHelper.java
index 82d6c836d72..b9e79d83717 100644
--- a/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/CoreDatatypeHelper.java
+++ b/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/CoreDatatypeHelper.java
@@ -19,7 +19,7 @@
@InternalUseOnly
class CoreDatatypeHelper {
- static Map reverseLookup;
+ private static Map reverseLookup;
static Map getReverseLookup() {
@@ -55,7 +55,7 @@ static class DatatypeIRI extends AbstractIRI {
public DatatypeIRI(String namespace, String localName) {
this.namespace = namespace;
this.localName = localName;
- this.stringValue = namespace.concat(localName);
+ this.stringValue = namespace.concat(localName).intern();
}
@Override
@@ -73,5 +73,9 @@ public String getLocalName() {
return localName;
}
+ @Override
+ public String toString() {
+ return stringValue;
+ }
}
}
diff --git a/core/model-api/src/test/java/org/eclipse/rdf4j/model/base/CoreDatatypeTest.java b/core/model-api/src/test/java/org/eclipse/rdf4j/model/base/CoreDatatypeTest.java
index cfe67e9c49a..0daa617ce1c 100644
--- a/core/model-api/src/test/java/org/eclipse/rdf4j/model/base/CoreDatatypeTest.java
+++ b/core/model-api/src/test/java/org/eclipse/rdf4j/model/base/CoreDatatypeTest.java
@@ -9,6 +9,8 @@
package org.eclipse.rdf4j.model.base;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
@@ -24,9 +26,9 @@ public class CoreDatatypeTest {
@Test
public void testOrderOfXSD() {
- ArrayList datatypes = getDatatypesShuffled();
+ ArrayList datatypes = getXSDDatatypesShuffled();
- List datatypeIRIs = getDatatypesShuffled().stream()
+ List datatypeIRIs = getXSDDatatypesShuffled().stream()
.map(CoreDatatype::getIri)
.map(Object::toString)
.collect(Collectors.toList());
@@ -42,13 +44,48 @@ public void testOrderOfXSD() {
}
- private ArrayList getDatatypesShuffled() {
- Random random = new Random(42353245);
+ @Test
+ public void testOrderOfRDF() {
+ ArrayList datatypes = getRDFDatatypesShuffled();
- ArrayList xsds = new ArrayList<>(Arrays.asList(CoreDatatype.XSD.values()));
+ List datatypeIRIs = getRDFDatatypesShuffled().stream()
+ .map(CoreDatatype::getIri)
+ .map(Object::toString)
+ .collect(Collectors.toList());
+
+ Collections.sort(datatypes);
+ Collections.sort(datatypeIRIs);
+
+ List datatypeIRIsSortedByEnum = datatypes.stream()
+ .map(CoreDatatype::getIri)
+ .map(Object::toString)
+ .collect(Collectors.toList());
+ Assert.assertEquals(datatypeIRIs, datatypeIRIsSortedByEnum);
+
+ }
+
+ private ArrayList getXSDDatatypesShuffled() {
+
+ ArrayList datatypes = new ArrayList<>(Arrays.asList(CoreDatatype.XSD.values()));
+
+ Collections.shuffle(datatypes, new Random(42353245));
+ return datatypes;
+ }
+
+ private ArrayList getRDFDatatypesShuffled() {
+
+ ArrayList datatypes = new ArrayList<>(Arrays.asList(CoreDatatype.RDF.values()));
+
+ Collections.shuffle(datatypes, new Random(42353245));
+ return datatypes;
+ }
+
+ @Test
+ public void testToString() {
+ for (CoreDatatype value : CoreDatatypeHelper.getReverseLookup().values()) {
+ assertSame(value.toString(), value.getIri().toString());
+ }
- Collections.shuffle(xsds);
- return xsds;
}
@Test
diff --git a/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/RDF.java b/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/RDF.java
index e210520988f..ba355e9c8c2 100644
--- a/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/RDF.java
+++ b/core/model-vocabulary/src/main/java/org/eclipse/rdf4j/model/vocabulary/RDF.java
@@ -32,77 +32,57 @@ public class RDF {
public static final Namespace NS = Vocabularies.createNamespace(PREFIX, NAMESPACE);
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#type */
- public final static IRI TYPE;
+ public final static IRI TYPE = Vocabularies.createIRI(RDF.NAMESPACE, "type");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#Property */
- public final static IRI PROPERTY;
+ public final static IRI PROPERTY = Vocabularies.createIRI(RDF.NAMESPACE, "Property");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral */
- public final static IRI XMLLITERAL;
+ public final static IRI XMLLITERAL = CoreDatatype.RDF.XMLLITERAL.getIri();
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#subject */
- public final static IRI SUBJECT;
+ public final static IRI SUBJECT = Vocabularies.createIRI(RDF.NAMESPACE, "subject");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate */
- public final static IRI PREDICATE;
+ public final static IRI PREDICATE = Vocabularies.createIRI(RDF.NAMESPACE, "predicate");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#object */
- public final static IRI OBJECT;
+ public final static IRI OBJECT = Vocabularies.createIRI(RDF.NAMESPACE, "object");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement */
- public final static IRI STATEMENT;
+ public final static IRI STATEMENT = Vocabularies.createIRI(RDF.NAMESPACE, "Statement");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag */
- public final static IRI BAG;
+ public final static IRI BAG = Vocabularies.createIRI(RDF.NAMESPACE, "Bag");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt */
- public final static IRI ALT;
+ public final static IRI ALT = Vocabularies.createIRI(RDF.NAMESPACE, "Alt");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq */
- public final static IRI SEQ;
+ public final static IRI SEQ = Vocabularies.createIRI(RDF.NAMESPACE, "Seq");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#value */
- public final static IRI VALUE;
+ public final static IRI VALUE = Vocabularies.createIRI(RDF.NAMESPACE, "value");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#li */
- public final static IRI LI;
+ public final static IRI LI = Vocabularies.createIRI(RDF.NAMESPACE, "li");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#List */
- public final static IRI LIST;
+ public final static IRI LIST = Vocabularies.createIRI(RDF.NAMESPACE, "List");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#first */
- public final static IRI FIRST;
+ public final static IRI FIRST = Vocabularies.createIRI(RDF.NAMESPACE, "first");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#rest */
- public final static IRI REST;
+ public final static IRI REST = Vocabularies.createIRI(RDF.NAMESPACE, "rest");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#nil */
- public final static IRI NIL;
+ public final static IRI NIL = Vocabularies.createIRI(RDF.NAMESPACE, "nil");
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#langString */
- public static final IRI LANGSTRING;
+ public static final IRI LANGSTRING = CoreDatatype.RDF.LANGSTRING.getIri();
/** http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML */
- public static final IRI HTML;
-
- static {
- TYPE = Vocabularies.createIRI(RDF.NAMESPACE, "type");
- PROPERTY = Vocabularies.createIRI(RDF.NAMESPACE, "Property");
- XMLLITERAL = Vocabularies.createIRI(RDF.NAMESPACE, "XMLLiteral");
- SUBJECT = Vocabularies.createIRI(RDF.NAMESPACE, "subject");
- PREDICATE = Vocabularies.createIRI(RDF.NAMESPACE, "predicate");
- OBJECT = Vocabularies.createIRI(RDF.NAMESPACE, "object");
- STATEMENT = Vocabularies.createIRI(RDF.NAMESPACE, "Statement");
- BAG = Vocabularies.createIRI(RDF.NAMESPACE, "Bag");
- ALT = Vocabularies.createIRI(RDF.NAMESPACE, "Alt");
- SEQ = Vocabularies.createIRI(RDF.NAMESPACE, "Seq");
- VALUE = Vocabularies.createIRI(RDF.NAMESPACE, "value");
- LI = Vocabularies.createIRI(RDF.NAMESPACE, "li");
- LIST = Vocabularies.createIRI(RDF.NAMESPACE, "List");
- FIRST = Vocabularies.createIRI(RDF.NAMESPACE, "first");
- REST = Vocabularies.createIRI(RDF.NAMESPACE, "rest");
- NIL = Vocabularies.createIRI(RDF.NAMESPACE, "nil");
- LANGSTRING = CoreDatatype.RDF.LANGSTRING.getIri();
- HTML = Vocabularies.createIRI(RDF.NAMESPACE, "HTML");
- }
+ public static final IRI HTML = CoreDatatype.RDF.HTML.getIri();
+
}
diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/datatypes/XMLDatatypeUtil.java b/core/model/src/main/java/org/eclipse/rdf4j/model/datatypes/XMLDatatypeUtil.java
index 6d297ddf2c3..77b51eaace7 100644
--- a/core/model/src/main/java/org/eclipse/rdf4j/model/datatypes/XMLDatatypeUtil.java
+++ b/core/model/src/main/java/org/eclipse/rdf4j/model/datatypes/XMLDatatypeUtil.java
@@ -315,77 +315,85 @@ public static boolean isValidValue(String value, IRI datatype) {
}
return true;
+
}
public static boolean isValidValue(String value, CoreDatatype datatype) {
if (datatype.isXSDDatatype()) {
- switch (((CoreDatatype.XSD) datatype)) {
- case DECIMAL:
- return isValidDecimal(value);
- case INTEGER:
- return isValidInteger(value);
- case NEGATIVE_INTEGER:
- return isValidNegativeInteger(value);
- case NON_POSITIVE_INTEGER:
- return isValidNonPositiveInteger(value);
- case NON_NEGATIVE_INTEGER:
- return isValidNonNegativeInteger(value);
- case POSITIVE_INTEGER:
- return isValidPositiveInteger(value);
- case LONG:
- return isValidLong(value);
- case INT:
- return isValidInt(value);
- case SHORT:
- return isValidShort(value);
- case BYTE:
- return isValidByte(value);
- case UNSIGNED_LONG:
- return isValidUnsignedLong(value);
- case UNSIGNED_INT:
- return isValidUnsignedInt(value);
- case UNSIGNED_SHORT:
- return isValidUnsignedShort(value);
- case UNSIGNED_BYTE:
- return isValidUnsignedByte(value);
- case FLOAT:
- return isValidFloat(value);
- case DOUBLE:
- return isValidDouble(value);
- case BOOLEAN:
- return isValidBoolean(value);
- case DATETIME:
- return isValidDateTime(value);
- case DATETIMESTAMP:
- return isValidDateTimeStamp(value);
- case DATE:
- return isValidDate(value);
- case TIME:
- return isValidTime(value);
- case GDAY:
- return isValidGDay(value);
- case GMONTH:
- return isValidGMonth(value);
- case GMONTHDAY:
- return isValidGMonthDay(value);
- case GYEAR:
- return isValidGYear(value);
- case GYEARMONTH:
- return isValidGYearMonth(value);
- case DURATION:
- return isValidDuration(value);
- case DAYTIMEDURATION:
- return isValidDayTimeDuration(value);
- case YEARMONTHDURATION:
- return isValidYearMonthDuration(value);
- case QNAME:
- return isValidQName(value);
- case ANYURI:
- return isValidAnyURI(value);
- case LANGUAGE:
- return Literals.isValidLanguageTag(value);
- }
+ return isValidValue(value, ((CoreDatatype.XSD) datatype));
+ }
+ return true;
+
+ }
+
+ public static boolean isValidValue(String value, CoreDatatype.XSD datatype) {
+ switch (datatype) {
+ case DECIMAL:
+ return isValidDecimal(value);
+ case INTEGER:
+ return isValidInteger(value);
+ case NEGATIVE_INTEGER:
+ return isValidNegativeInteger(value);
+ case NON_POSITIVE_INTEGER:
+ return isValidNonPositiveInteger(value);
+ case NON_NEGATIVE_INTEGER:
+ return isValidNonNegativeInteger(value);
+ case POSITIVE_INTEGER:
+ return isValidPositiveInteger(value);
+ case LONG:
+ return isValidLong(value);
+ case INT:
+ return isValidInt(value);
+ case SHORT:
+ return isValidShort(value);
+ case BYTE:
+ return isValidByte(value);
+ case UNSIGNED_LONG:
+ return isValidUnsignedLong(value);
+ case UNSIGNED_INT:
+ return isValidUnsignedInt(value);
+ case UNSIGNED_SHORT:
+ return isValidUnsignedShort(value);
+ case UNSIGNED_BYTE:
+ return isValidUnsignedByte(value);
+ case FLOAT:
+ return isValidFloat(value);
+ case DOUBLE:
+ return isValidDouble(value);
+ case BOOLEAN:
+ return isValidBoolean(value);
+ case DATETIME:
+ return isValidDateTime(value);
+ case DATETIMESTAMP:
+ return isValidDateTimeStamp(value);
+ case DATE:
+ return isValidDate(value);
+ case TIME:
+ return isValidTime(value);
+ case GDAY:
+ return isValidGDay(value);
+ case GMONTH:
+ return isValidGMonth(value);
+ case GMONTHDAY:
+ return isValidGMonthDay(value);
+ case GYEAR:
+ return isValidGYear(value);
+ case GYEARMONTH:
+ return isValidGYearMonth(value);
+ case DURATION:
+ return isValidDuration(value);
+ case DAYTIMEDURATION:
+ return isValidDayTimeDuration(value);
+ case YEARMONTHDURATION:
+ return isValidYearMonthDuration(value);
+ case QNAME:
+ return isValidQName(value);
+ case ANYURI:
+ return isValidAnyURI(value);
+ case LANGUAGE:
+ return Literals.isValidLanguageTag(value);
}
+
return true;
}
@@ -890,95 +898,93 @@ private static boolean isValidCalendarValue(String value) {
* @throws IllegalArgumentException If the supplied value is illegal considering the supplied datatype.
*/
public static String normalize(String value, IRI datatype) {
- String result = value;
-
if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.DECIMAL)) {
- result = normalizeDecimal(value);
+ return normalizeDecimal(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.INTEGER)) {
- result = normalizeInteger(value);
+ return normalizeInteger(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.NEGATIVE_INTEGER)) {
- result = normalizeNegativeInteger(value);
+ return normalizeNegativeInteger(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.NON_POSITIVE_INTEGER)) {
- result = normalizeNonPositiveInteger(value);
+ return normalizeNonPositiveInteger(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.NON_NEGATIVE_INTEGER)) {
- result = normalizeNonNegativeInteger(value);
+ return normalizeNonNegativeInteger(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.POSITIVE_INTEGER)) {
- result = normalizePositiveInteger(value);
+ return normalizePositiveInteger(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.LONG)) {
- result = normalizeLong(value);
+ return normalizeLong(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.INT)) {
- result = normalizeInt(value);
+ return normalizeInt(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.SHORT)) {
- result = normalizeShort(value);
+ return normalizeShort(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.BYTE)) {
- result = normalizeByte(value);
+ return normalizeByte(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.UNSIGNED_LONG)) {
- result = normalizeUnsignedLong(value);
+ return normalizeUnsignedLong(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.UNSIGNED_INT)) {
- result = normalizeUnsignedInt(value);
+ return normalizeUnsignedInt(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.UNSIGNED_SHORT)) {
- result = normalizeUnsignedShort(value);
+ return normalizeUnsignedShort(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.UNSIGNED_BYTE)) {
- result = normalizeUnsignedByte(value);
+ return normalizeUnsignedByte(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.FLOAT)) {
- result = normalizeFloat(value);
+ return normalizeFloat(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.DOUBLE)) {
- result = normalizeDouble(value);
+ return normalizeDouble(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.BOOLEAN)) {
- result = normalizeBoolean(value);
+ return normalizeBoolean(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.DATETIME)) {
- result = normalizeDateTime(value);
+ return normalizeDateTime(value);
} else if (datatype.equals(org.eclipse.rdf4j.model.vocabulary.XSD.ANYURI)) {
- result = collapseWhiteSpace(value);
+ return collapseWhiteSpace(value);
}
- return result;
+ return value;
}
public static String normalize(String value, CoreDatatype.XSD datatype) {
- String result = value;
-
- if (datatype == CoreDatatype.XSD.DECIMAL) {
- result = normalizeDecimal(value);
- } else if (datatype == CoreDatatype.XSD.INTEGER) {
- result = normalizeInteger(value);
- } else if (datatype == CoreDatatype.XSD.NEGATIVE_INTEGER) {
- result = normalizeNegativeInteger(value);
- } else if (datatype == CoreDatatype.XSD.NON_POSITIVE_INTEGER) {
- result = normalizeNonPositiveInteger(value);
- } else if (datatype == CoreDatatype.XSD.NON_NEGATIVE_INTEGER) {
- result = normalizeNonNegativeInteger(value);
- } else if (datatype == CoreDatatype.XSD.POSITIVE_INTEGER) {
- result = normalizePositiveInteger(value);
- } else if (datatype == CoreDatatype.XSD.LONG) {
- result = normalizeLong(value);
- } else if (datatype == CoreDatatype.XSD.INT) {
- result = normalizeInt(value);
- } else if (datatype == CoreDatatype.XSD.SHORT) {
- result = normalizeShort(value);
- } else if (datatype == CoreDatatype.XSD.BYTE) {
- result = normalizeByte(value);
- } else if (datatype == CoreDatatype.XSD.UNSIGNED_LONG) {
- result = normalizeUnsignedLong(value);
- } else if (datatype == CoreDatatype.XSD.UNSIGNED_INT) {
- result = normalizeUnsignedInt(value);
- } else if (datatype == CoreDatatype.XSD.UNSIGNED_SHORT) {
- result = normalizeUnsignedShort(value);
- } else if (datatype == CoreDatatype.XSD.UNSIGNED_BYTE) {
- result = normalizeUnsignedByte(value);
- } else if (datatype == CoreDatatype.XSD.FLOAT) {
- result = normalizeFloat(value);
- } else if (datatype == CoreDatatype.XSD.DOUBLE) {
- result = normalizeDouble(value);
- } else if (datatype == CoreDatatype.XSD.BOOLEAN) {
- result = normalizeBoolean(value);
- } else if (datatype == CoreDatatype.XSD.DATETIME) {
- result = normalizeDateTime(value);
- } else if (datatype == CoreDatatype.XSD.ANYURI) {
- result = collapseWhiteSpace(value);
- }
- return result;
+ switch (datatype) {
+ case DECIMAL:
+ return normalizeDecimal(value);
+ case INTEGER:
+ return normalizeInteger(value);
+ case NEGATIVE_INTEGER:
+ return normalizeNegativeInteger(value);
+ case NON_POSITIVE_INTEGER:
+ return normalizeNonPositiveInteger(value);
+ case NON_NEGATIVE_INTEGER:
+ return normalizeNonNegativeInteger(value);
+ case POSITIVE_INTEGER:
+ return normalizePositiveInteger(value);
+ case LONG:
+ return normalizeLong(value);
+ case INT:
+ return normalizeInt(value);
+ case SHORT:
+ return normalizeShort(value);
+ case BYTE:
+ return normalizeByte(value);
+ case UNSIGNED_LONG:
+ return normalizeUnsignedLong(value);
+ case UNSIGNED_INT:
+ return normalizeUnsignedInt(value);
+ case UNSIGNED_SHORT:
+ return normalizeUnsignedShort(value);
+ case UNSIGNED_BYTE:
+ return normalizeUnsignedByte(value);
+ case FLOAT:
+ return normalizeFloat(value);
+ case DOUBLE:
+ return normalizeDouble(value);
+ case BOOLEAN:
+ return normalizeBoolean(value);
+ case DATETIME:
+ return normalizeDateTime(value);
+ case ANYURI:
+ return collapseWhiteSpace(value);
+ }
+
+ return value;
}
/**
@@ -2137,6 +2143,34 @@ public static IRI qnameToURI(QName qname) {
}
}
+ public static CoreDatatype.XSD qnameToCoreDatatype(QName qname) {
+ if (DatatypeConstants.DATETIME == qname) {
+ return CoreDatatype.XSD.DATETIME;
+ } else if (DatatypeConstants.DATE == qname) {
+ return CoreDatatype.XSD.DATE;
+ } else if (DatatypeConstants.TIME == qname) {
+ return CoreDatatype.XSD.TIME;
+ } else if (DatatypeConstants.GYEARMONTH == qname) {
+ return CoreDatatype.XSD.GYEARMONTH;
+ } else if (DatatypeConstants.GMONTHDAY == qname) {
+ return CoreDatatype.XSD.GMONTHDAY;
+ } else if (DatatypeConstants.GYEAR == qname) {
+ return CoreDatatype.XSD.GYEAR;
+ } else if (DatatypeConstants.GMONTH == qname) {
+ return CoreDatatype.XSD.GMONTH;
+ } else if (DatatypeConstants.GDAY == qname) {
+ return CoreDatatype.XSD.GDAY;
+ } else if (DatatypeConstants.DURATION == qname) {
+ return CoreDatatype.XSD.DURATION;
+ } else if (DatatypeConstants.DURATION_DAYTIME == qname) {
+ return CoreDatatype.XSD.DAYTIMEDURATION;
+ } else if (DatatypeConstants.DURATION_YEARMONTH == qname) {
+ return CoreDatatype.XSD.YEARMONTHDURATION;
+ } else {
+ throw new IllegalArgumentException("QName cannot be mapped to an XML Schema IRI: " + qname.toString());
+ }
+ }
+
public static String toString(Number value) {
double d = value.doubleValue();
if (Double.POSITIVE_INFINITY == d) {
diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/BooleanLiteral.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/BooleanLiteral.java
index e5b8dd8e46b..39f8014dfdb 100644
--- a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/BooleanLiteral.java
+++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/BooleanLiteral.java
@@ -7,6 +7,9 @@
*******************************************************************************/
package org.eclipse.rdf4j.model.impl;
+import java.util.Optional;
+
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.vocabulary.XSD;
/**
@@ -61,4 +64,9 @@ public boolean booleanValue() {
public static BooleanLiteral valueOf(boolean value) {
return value ? TRUE : FALSE;
}
+
+ @Override
+ public CoreDatatype.XSD getCoreDatatype() {
+ return CoreDatatype.XSD.BOOLEAN;
+ }
}
diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/CalendarLiteral.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/CalendarLiteral.java
index 2afaf23c54d..67f03cf40fa 100644
--- a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/CalendarLiteral.java
+++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/CalendarLiteral.java
@@ -28,7 +28,7 @@ public class CalendarLiteral extends SimpleLiteral {
* {@link XMLGregorianCalendar#getXMLSchemaType()}.
*/
protected CalendarLiteral(XMLGregorianCalendar calendar) {
- super(calendar.toXMLFormat(), XMLDatatypeUtil.qnameToURI(calendar.getXMLSchemaType()));
+ super(calendar.toXMLFormat(), XMLDatatypeUtil.qnameToCoreDatatype(calendar.getXMLSchemaType()));
this.calendar = calendar;
}
diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/DecimalLiteral.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/DecimalLiteral.java
index 094eca3675e..966c644b938 100644
--- a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/DecimalLiteral.java
+++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/DecimalLiteral.java
@@ -29,7 +29,7 @@ public class DecimalLiteral extends SimpleLiteral {
* Creates an xsd:decimal literal with the specified value.
*/
protected DecimalLiteral(BigDecimal value) {
- this(value, XSD.DECIMAL);
+ this(value, CoreDatatype.XSD.DECIMAL);
}
/**
diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/NumericLiteral.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/NumericLiteral.java
index 3b471ffcf30..b6edda14be0 100644
--- a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/NumericLiteral.java
+++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/NumericLiteral.java
@@ -46,42 +46,42 @@ protected NumericLiteral(Number number, CoreDatatype datatype) {
* Creates an xsd:byte typed litral with the specified value.
*/
protected NumericLiteral(byte number) {
- this(number, XSD.BYTE);
+ this(number, CoreDatatype.XSD.BYTE);
}
/**
* Creates an xsd:short typed litral with the specified value.
*/
protected NumericLiteral(short number) {
- this(number, XSD.SHORT);
+ this(number, CoreDatatype.XSD.SHORT);
}
/**
* Creates an xsd:int typed litral with the specified value.
*/
protected NumericLiteral(int number) {
- this(number, XSD.INT);
+ this(number, CoreDatatype.XSD.INT);
}
/**
* Creates an xsd:long typed litral with the specified value.
*/
protected NumericLiteral(long n) {
- this(n, XSD.LONG);
+ this(n, CoreDatatype.XSD.LONG);
}
/**
* Creates an xsd:float typed litral with the specified value.
*/
protected NumericLiteral(float n) {
- this(n, XSD.FLOAT);
+ this(n, CoreDatatype.XSD.FLOAT);
}
/**
* Creates an xsd:double typed litral with the specified value.
*/
protected NumericLiteral(double n) {
- this(n, XSD.DOUBLE);
+ this(n, CoreDatatype.XSD.DOUBLE);
}
@Override
diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleLiteral.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleLiteral.java
index 39121fac77a..97dcc35057d 100644
--- a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleLiteral.java
+++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleLiteral.java
@@ -49,6 +49,7 @@ public class SimpleLiteral extends AbstractLiteral {
* The literal's language tag.
*/
private String language;
+ transient private Optional optionalLanguageCache = null;
/**
* The literal's datatype.
@@ -72,6 +73,7 @@ protected SimpleLiteral() {
protected SimpleLiteral(String label) {
setLabel(label);
setDatatype(org.eclipse.rdf4j.model.vocabulary.XSD.STRING);
+ optionalLanguageCache = Optional.empty();
}
/**
@@ -100,6 +102,28 @@ protected SimpleLiteral(String label, IRI datatype) {
} else {
setDatatype(datatype);
}
+ optionalLanguageCache = Optional.empty();
+
+ }
+
+ /**
+ * Creates a new datatyped literal with the supplied label and datatype.
+ *
+ * @param label The label for the literal, must not be null.
+ * @param datatype The datatype for the literal.
+ */
+ protected SimpleLiteral(String label, IRI datatype, CoreDatatype coreDatatype) {
+ assert coreDatatype != null;
+ assert datatype != null;
+ assert coreDatatype == CoreDatatype.NONE || datatype == coreDatatype.getIri();
+
+ if (CoreDatatype.RDF.LANGSTRING == coreDatatype) {
+ throw new IllegalArgumentException("datatype rdf:langString requires a language tag");
+ }
+
+ setLabel(label);
+ setDatatype(datatype, coreDatatype);
+ optionalLanguageCache = Optional.empty();
}
@Deprecated(since = "4.0.0", forRemoval = true)
@@ -122,6 +146,7 @@ protected SimpleLiteral(String label, CoreDatatype datatype) {
} else {
setDatatype(datatype);
}
+ optionalLanguageCache = Optional.empty();
}
@@ -145,12 +170,16 @@ protected void setLanguage(String language) {
throw new IllegalArgumentException("Language tag cannot be empty");
}
this.language = language;
- setDatatype(org.eclipse.rdf4j.model.vocabulary.RDF.LANGSTRING);
+ optionalLanguageCache = Optional.of(language);
+ setDatatype(CoreDatatype.RDF.LANGSTRING);
}
@Override
public Optional getLanguage() {
- return Optional.ofNullable(language);
+ if (optionalLanguageCache == null) {
+ optionalLanguageCache = Optional.ofNullable(language);
+ }
+ return optionalLanguageCache;
}
protected void setDatatype(IRI datatype) {
@@ -158,6 +187,16 @@ protected void setDatatype(IRI datatype) {
coreDatatype = CoreDatatype.from(datatype);
}
+ protected void setDatatype(IRI datatype, CoreDatatype coreDatatype) {
+ assert datatype != null;
+ assert coreDatatype != null;
+ assert coreDatatype == CoreDatatype.NONE || datatype == coreDatatype.getIri();
+
+ this.datatype = datatype;
+ this.coreDatatype = coreDatatype;
+
+ }
+
@Deprecated(since = "4.0.0", forRemoval = true)
protected void setDatatype(XSD.Datatype datatype) {
this.datatype = datatype.getIri();
@@ -165,6 +204,7 @@ protected void setDatatype(XSD.Datatype datatype) {
}
protected void setDatatype(CoreDatatype datatype) {
+ Objects.requireNonNull(datatype);
this.datatype = datatype.getIri();
this.coreDatatype = datatype;
}
@@ -195,22 +235,32 @@ public boolean equals(Object o) {
if (o instanceof Literal) {
Literal other = (Literal) o;
- // Compare labels
- if (!label.equals(other.getLabel())) {
+ CoreDatatype coreDatatype = getCoreDatatype();
+
+ // Compare core datatypes
+ if (coreDatatype != ((Literal) o).getCoreDatatype()) {
return false;
+ } else if (coreDatatype == CoreDatatype.NONE) {
+ // Compare other datatypes
+ if (!datatype.equals(other.getDatatype())) {
+ return false;
+ }
}
- // Compare datatypes
- if (!datatype.equals(other.getDatatype())) {
+ // Compare labels
+ if (!label.equals(other.getLabel())) {
return false;
}
- if (getLanguage().isPresent() && other.getLanguage().isPresent()) {
- return getLanguage().get().equalsIgnoreCase(other.getLanguage().get());
+ Optional language = getLanguage();
+ Optional otherLanguage = other.getLanguage();
+
+ if (language.isPresent() && otherLanguage.isPresent()) {
+ return language.get().equalsIgnoreCase(otherLanguage.get());
}
// If only one has a language, then return false
else {
- return !getLanguage().isPresent() && !other.getLanguage().isPresent();
+ return language.isEmpty() && otherLanguage.isEmpty();
}
}
diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleValueFactory.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleValueFactory.java
index fd78937256a..d8dcb716df2 100644
--- a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleValueFactory.java
+++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/SimpleValueFactory.java
@@ -288,11 +288,11 @@ protected Literal createNumericLiteral(Number number, CoreDatatype datatype) {
*
* @see XMLGregorianCalendar#toXMLFormat()
* @see XMLGregorianCalendar#getXMLSchemaType()
- * @see XMLDatatypeUtil#qnameToURI(javax.xml.namespace.QName)
+ * @see XMLDatatypeUtil#qnameToCoreDatatype(javax.xml.namespace.QName)
*/
@Override
public Literal createLiteral(XMLGregorianCalendar calendar) {
- return createLiteral(calendar.toXMLFormat(), XMLDatatypeUtil.qnameToURI(calendar.getXMLSchemaType()));
+ return createLiteral(calendar.toXMLFormat(), XMLDatatypeUtil.qnameToCoreDatatype(calendar.getXMLSchemaType()));
}
/**
diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ValidatingValueFactory.java b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ValidatingValueFactory.java
index 52641a79b93..e85efa00988 100644
--- a/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ValidatingValueFactory.java
+++ b/core/model/src/main/java/org/eclipse/rdf4j/model/impl/ValidatingValueFactory.java
@@ -121,6 +121,14 @@ public Literal createLiteral(String label, CoreDatatype datatype) {
return delegate.createLiteral(label, datatype);
}
+ @Override
+ public Literal createLiteral(String label, IRI datatype, CoreDatatype coreDatatype) {
+ if (!XMLDatatypeUtil.isValidValue(label, coreDatatype)) {
+ throw new IllegalArgumentException("Not a valid literal value");
+ }
+ return delegate.createLiteral(label, datatype, coreDatatype);
+ }
+
@Override
public Literal createLiteral(String label, String language) {
if (!Literals.isValidLanguageTag(language)) {
diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/Literals.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/Literals.java
index 61dc8654aa6..262a9ee357a 100644
--- a/core/model/src/main/java/org/eclipse/rdf4j/model/util/Literals.java
+++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/Literals.java
@@ -12,7 +12,6 @@
import java.util.Date;
import java.util.IllformedLocaleException;
import java.util.Locale;
-import java.util.Objects;
import java.util.Optional;
import javax.xml.datatype.Duration;
@@ -21,6 +20,7 @@
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.ValueFactory;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
import org.eclipse.rdf4j.model.impl.SimpleLiteral;
import org.eclipse.rdf4j.model.vocabulary.XSD;
@@ -439,30 +439,30 @@ private static Literal createLiteral(ValueFactory valueFactory, Object object, b
}
if (object instanceof Boolean) {
- return valueFactory.createLiteral(((Boolean) object).booleanValue());
+ return valueFactory.createLiteral((Boolean) object);
} else if (object instanceof Byte) {
- return valueFactory.createLiteral(((Byte) object).byteValue());
+ return valueFactory.createLiteral((Byte) object);
} else if (object instanceof Double) {
- return valueFactory.createLiteral(((Double) object).doubleValue());
+ return valueFactory.createLiteral((Double) object);
} else if (object instanceof Float) {
- return valueFactory.createLiteral(((Float) object).floatValue());
+ return valueFactory.createLiteral((Float) object);
} else if (object instanceof Integer) {
- return valueFactory.createLiteral(((Integer) object).intValue());
+ return valueFactory.createLiteral((Integer) object);
} else if (object instanceof Long) {
- return valueFactory.createLiteral(((Long) object).longValue());
+ return valueFactory.createLiteral((Long) object);
} else if (object instanceof Short) {
- return valueFactory.createLiteral(((Short) object).shortValue());
+ return valueFactory.createLiteral((Short) object);
} else if (object instanceof XMLGregorianCalendar) {
return valueFactory.createLiteral((XMLGregorianCalendar) object);
} else if (object instanceof Date) {
return valueFactory.createLiteral((Date) object);
} else if (object instanceof String) {
- return valueFactory.createLiteral(object.toString(), XSD.STRING);
+ return valueFactory.createLiteral(object.toString(), CoreDatatype.XSD.STRING);
} else {
if (throwExceptionOnFailure) {
throw new LiteralUtilException("Did not recognise object when creating literal");
}
- return valueFactory.createLiteral(object.toString(), XSD.STRING);
+ return valueFactory.createLiteral(object.toString(), CoreDatatype.XSD.STRING);
}
}
@@ -484,13 +484,10 @@ public static boolean canCreateLiteral(Object object) {
return false;
}
- if (object instanceof Boolean || object instanceof Byte || object instanceof Double || object instanceof Float
+ return object instanceof Boolean || object instanceof Byte || object instanceof Double
+ || object instanceof Float
|| object instanceof Integer || object instanceof Long || object instanceof Short
- || object instanceof XMLGregorianCalendar || object instanceof Date || object instanceof String) {
- return true;
- }
-
- return false;
+ || object instanceof XMLGregorianCalendar || object instanceof Date || object instanceof String;
}
/**
@@ -500,7 +497,7 @@ public static boolean canCreateLiteral(Object object) {
* @return True if the literal has a language tag attached to it and false otherwise.
*/
public static boolean isLanguageLiteral(Literal literal) {
- return Objects.requireNonNull(literal, "Literal cannot be null").getLanguage().isPresent();
+ return literal.getCoreDatatype() == CoreDatatype.RDF.LANGSTRING;
}
/**
diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/ModelBuilder.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/ModelBuilder.java
index 3b34af7d2db..fe26525f59f 100644
--- a/core/model/src/main/java/org/eclipse/rdf4j/model/util/ModelBuilder.java
+++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/ModelBuilder.java
@@ -19,6 +19,7 @@
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.ValueFactory;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.impl.LinkedHashModel;
import org.eclipse.rdf4j.model.impl.SimpleNamespace;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
@@ -41,13 +42,13 @@
*
* ModelBuilder builder = new ModelBuilder();
*
- * // set some namespaces
+ * // set some namespaces
* builder.setNamespace("ex", "http://example.org/").setNamespace(FOAF.NS);
*
* // add a new named graph to the model
* builder.namedGraph("ex:graph1")
* // add statements about resource ex:john
- * .subject("ex:john")
+ * .subject("ex:john")
* .add(FOAF.NAME, "John") // add the triple (ex:john, foaf:name "John") to the named graph
* .add(FOAF.AGE, 42)
* .add(FOAF.MBOX, "john@example.org");
@@ -79,7 +80,7 @@ public ModelBuilder() {
/**
* Create a new {@link ModelBuilder} which will append to the supplied {@link Model}.
- *
+ *
* @param model
*/
public ModelBuilder(Model model) {
@@ -202,7 +203,7 @@ public ModelBuilder add(Resource subject, IRI predicate, Object object) {
if (objectValue == null) {
Literal literal = Values.literal(object);
- if (!literal.getDatatype().equals(XSD.STRING)) {
+ if (literal.getCoreDatatype() != CoreDatatype.XSD.STRING) {
model.setNamespace(XSD.NS);
}
objectValue = literal;
diff --git a/core/model/src/main/java/org/eclipse/rdf4j/model/util/Values.java b/core/model/src/main/java/org/eclipse/rdf4j/model/util/Values.java
index 6fdc101c019..02f3cf20632 100644
--- a/core/model/src/main/java/org/eclipse/rdf4j/model/util/Values.java
+++ b/core/model/src/main/java/org/eclipse/rdf4j/model/util/Values.java
@@ -789,19 +789,19 @@ private static Literal createLiteralFromObject(ValueFactory valueFactory, Object
Objects.requireNonNull(object, "object may not be null");
if (object instanceof Boolean) {
- return valueFactory.createLiteral(((Boolean) object).booleanValue());
+ return valueFactory.createLiteral((Boolean) object);
} else if (object instanceof Byte) {
- return valueFactory.createLiteral(((Byte) object).byteValue());
+ return valueFactory.createLiteral((Byte) object);
} else if (object instanceof Double) {
- return valueFactory.createLiteral(((Double) object).doubleValue());
+ return valueFactory.createLiteral((Double) object);
} else if (object instanceof Float) {
- return valueFactory.createLiteral(((Float) object).floatValue());
+ return valueFactory.createLiteral((Float) object);
} else if (object instanceof Integer) {
- return valueFactory.createLiteral(((Integer) object).intValue());
+ return valueFactory.createLiteral((Integer) object);
} else if (object instanceof Long) {
- return valueFactory.createLiteral(((Long) object).longValue());
+ return valueFactory.createLiteral((Long) object);
} else if (object instanceof Short) {
- return valueFactory.createLiteral(((Short) object).shortValue());
+ return valueFactory.createLiteral((Short) object);
} else if (object instanceof XMLGregorianCalendar) {
return valueFactory.createLiteral((XMLGregorianCalendar) object);
} else if (object instanceof Date) {
@@ -809,12 +809,12 @@ private static Literal createLiteralFromObject(ValueFactory valueFactory, Object
} else if (object instanceof TemporalAccessor) {
return valueFactory.createLiteral((TemporalAccessor) object);
} else if (object instanceof String) {
- return valueFactory.createLiteral(object.toString(), XSD.STRING);
+ return valueFactory.createLiteral(object.toString(), CoreDatatype.XSD.STRING);
} else {
if (throwExceptionOnFailure) {
throw new IllegalArgumentException("Unrecognized object type: " + object);
}
- return valueFactory.createLiteral(object.toString(), XSD.STRING);
+ return valueFactory.createLiteral(object.toString(), CoreDatatype.XSD.STRING);
}
}
}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/ArrayBindingSet.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/ArrayBindingSet.java
index 57b7654d393..93c7835e7c4 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/ArrayBindingSet.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/ArrayBindingSet.java
@@ -7,9 +7,12 @@
*******************************************************************************/
package org.eclipse.rdf4j.query.algebra.evaluation;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Function;
@@ -34,6 +37,9 @@ public class ArrayBindingSet extends AbstractBindingSet implements MutableBindin
private final String[] bindingNames;
+ // Creating a LinkedHashSet is expensive, so we should cache the binding names set
+ private Set bindingNamesSetCache;
+
private final boolean[] whichBindingsHaveBeenSet;
private final Value[] values;
@@ -83,7 +89,7 @@ public ArrayBindingSet(ArrayBindingSet toCopy, String... names) {
/**
* This is used to generate a direct setter into the array to put a binding value into. Can be used to avoid many
* comparisons to the bindingNames.
- *
+ *
* @param bindingName for which you want the setter
* @return the setter biconsumer which can operate on any ArrayBindingSet but should only be used on ones with an
* identical bindingNames array. Otherwise returns null.
@@ -95,6 +101,7 @@ public BiConsumer getDirectSetBinding(String bindingName
return (v, a) -> {
a.values[idx] = v;
a.whichBindingsHaveBeenSet[idx] = true;
+ a.clearCache();
};
}
}
@@ -110,6 +117,7 @@ public BiConsumer getDirectAddBinding(String bindingName
assert !a.whichBindingsHaveBeenSet[idx] : "variable already bound: " + bindingName;
a.values[idx] = v;
a.whichBindingsHaveBeenSet[idx] = true;
+ a.clearCache();
};
}
}
@@ -158,19 +166,38 @@ public Function getDirectHasBinding(String bindingName
@Override
public Set getBindingNames() {
- final LinkedHashSet bns = new LinkedHashSet<>();
- for (int i = 0; i < this.bindingNames.length; i++) {
- if (values[i] != null)
- bns.add(bindingNames[i]);
+ if (bindingNamesSetCache == null) {
+ int size = size();
+ if (size == 0) {
+ this.bindingNamesSetCache = Collections.emptySet();
+ } else if (size == 1) {
+ for (int i = 0; i < this.bindingNames.length; i++) {
+ if (whichBindingsHaveBeenSet[i]) {
+ this.bindingNamesSetCache = Collections.singleton(bindingNames[i]);
+ break;
+ }
+ }
+ assert this.bindingNamesSetCache != null;
+ } else {
+ LinkedHashSet bindingNamesSetCache = new LinkedHashSet<>(size * 2);
+ for (int i = 0; i < this.bindingNames.length; i++) {
+ if (whichBindingsHaveBeenSet[i]) {
+ bindingNamesSetCache.add(bindingNames[i]);
+ }
+ }
+ this.bindingNamesSetCache = Collections.unmodifiableSet(bindingNamesSetCache);
+ }
}
- return bns;
+
+ return bindingNamesSetCache;
}
@Override
public Value getValue(String bindingName) {
for (int i = 0; i < bindingNames.length; i++) {
- if (bindingNames[i].equals(bindingName) && whichBindingsHaveBeenSet[i])
+ if (bindingNames[i].equals(bindingName) && whichBindingsHaveBeenSet[i]) {
return values[i];
+ }
}
return null;
}
@@ -189,8 +216,9 @@ public Binding getBinding(String bindingName) {
@Override
public boolean hasBinding(String bindingName) {
for (int i = 0; i < bindingNames.length; i++) {
- if (bindingNames[i].equals(bindingName))
+ if (bindingNames[i].equals(bindingName)) {
return whichBindingsHaveBeenSet[i];
+ }
}
return false;
}
@@ -213,6 +241,33 @@ public int size() {
return size;
}
+ List sortedBindingNames = null;
+
+ public List getSortedBindingNames() {
+ if (sortedBindingNames == null) {
+ int size = size();
+
+ if (size == 1) {
+ for (int i = 0; i < bindingNames.length; i++) {
+ if (whichBindingsHaveBeenSet[i]) {
+ sortedBindingNames = Collections.singletonList(bindingNames[i]);
+ }
+ }
+ } else {
+ ArrayList names = new ArrayList<>(size);
+ for (int i = 0; i < bindingNames.length; i++) {
+ if (whichBindingsHaveBeenSet[i]) {
+ names.add(bindingNames[i]);
+ }
+ }
+ names.sort(String::compareTo);
+ sortedBindingNames = names;
+ }
+ }
+
+ return sortedBindingNames;
+ }
+
/*------------------------------------*
* Inner class ArrayBindingSetIterator *
*------------------------------------*/
@@ -239,10 +294,11 @@ public Binding next() {
String name = bindingNames[index];
Value value = values[index++];
- if (value != null)
+ if (value != null) {
return new SimpleBinding(name, value);
- else
+ } else {
return null;
+ }
}
@Override
@@ -255,11 +311,14 @@ public void remove() {
public void addBinding(Binding binding) {
for (int i = 0; i < this.bindingNames.length; i++) {
if (bindingNames[i].equals(binding.getName())) {
- assert this.whichBindingsHaveBeenSet[i] == false;
+ assert !this.whichBindingsHaveBeenSet[i];
this.values[i] = binding.getValue();
this.whichBindingsHaveBeenSet[i] = true;
+ clearCache();
+ return;
}
}
+ assert false : "We don't actually support adding a binding.";
}
@Override
@@ -268,6 +327,8 @@ public void setBinding(Binding binding) {
if (bindingNames[i].equals(binding.getName())) {
this.values[i] = binding.getValue();
this.whichBindingsHaveBeenSet[i] = true;
+ clearCache();
+ return;
}
}
}
@@ -278,6 +339,8 @@ public void setBinding(String name, Value value) {
if (bindingNames[i].equals(name)) {
this.values[i] = value;
this.whichBindingsHaveBeenSet[i] = value != null;
+ clearCache();
+ return;
}
}
}
@@ -291,4 +354,8 @@ public boolean isEmpty() {
}
return true;
}
+
+ private void clearCache() {
+ bindingNamesSetCache = null;
+ }
}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/EvaluationStrategy.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/EvaluationStrategy.java
index f5656cef14a..51c2331cd8f 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/EvaluationStrategy.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/EvaluationStrategy.java
@@ -94,7 +94,7 @@ CloseableIteration evaluate(TupleExpr expr
/**
* Prepare a QueryEvaluationStep that tries to do as much work once per query avoiding repeated calls to the same
* code as much as possible. This depends on java invoke dynamic for performance.
- *
+ *
* @param expr that is to be evaluated later
* @return a QueryEvaluationStep that may avoid doing repeating the same work over and over.
*/
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryEvaluationStep.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryEvaluationStep.java
index 691d6e0cee4..a2a688d500d 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryEvaluationStep.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/QueryEvaluationStep.java
@@ -47,7 +47,7 @@ public DelayedEvaluationIteration(QueryEvaluationStep arg, BindingSet bs) {
/**
* A fall back implementation that wraps a pre-existing evaluate method on a strategy
- *
+ *
* @param strategy that can evaluate the tuple expr.
* @param expr that is going to be evaluated
* @return a thin wrapper arround the evaluation call.
@@ -64,7 +64,7 @@ public CloseableIteration evaluate(Binding
/**
* Wrap an QueryEvalationStep: where we apply a function on every evaluation result of the wrapped EvaluationStep.
* Useful to add a timing function
- *
+ *
* @param qes an QueryEvaluationStep that needs to return modified evaluation results
* @param wrap the function that will do the modification
* @return a new evaluation step that executes wrap on the inner qes.
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/MD5.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/MD5.java
index 7858fd1e76f..186441d2a23 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/MD5.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/MD5.java
@@ -15,7 +15,7 @@
import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} MD5, as defined in
@@ -39,7 +39,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
if (args[0] instanceof Literal) {
Literal literal = (Literal) args[0];
- if (QueryEvaluationUtil.isSimpleLiteral(literal) || XSD.STRING.equals(literal.getDatatype())) {
+ if (QueryEvaluationUtility.isSimpleLiteral(literal) || XSD.STRING.equals(literal.getDatatype())) {
String lexValue = literal.getLabel();
try {
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA1.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA1.java
index f98370359ab..8cfe2c6ec29 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA1.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA1.java
@@ -15,7 +15,7 @@
import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} SHA1, as defined in
@@ -39,7 +39,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
if (args[0] instanceof Literal) {
Literal literal = (Literal) args[0];
- if (QueryEvaluationUtil.isSimpleLiteral(literal) || XSD.STRING.equals(literal.getDatatype())) {
+ if (QueryEvaluationUtility.isSimpleLiteral(literal) || XSD.STRING.equals(literal.getDatatype())) {
String lexValue = literal.getLabel();
try {
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA256.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA256.java
index a985f2f123e..2c8c4be1970 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA256.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA256.java
@@ -15,7 +15,7 @@
import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} SHA256, as defined in
@@ -39,7 +39,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
if (args[0] instanceof Literal) {
Literal literal = (Literal) args[0];
- if (QueryEvaluationUtil.isSimpleLiteral(literal) || XSD.STRING.equals(literal.getDatatype())) {
+ if (QueryEvaluationUtility.isSimpleLiteral(literal) || XSD.STRING.equals(literal.getDatatype())) {
String lexValue = literal.getLabel();
try {
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA384.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA384.java
index f3a80800e01..7f6bf26b3e7 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA384.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA384.java
@@ -15,7 +15,7 @@
import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} SHA384, as defined in
@@ -39,7 +39,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
if (args[0] instanceof Literal) {
Literal literal = (Literal) args[0];
- if (QueryEvaluationUtil.isSimpleLiteral(literal) || XSD.STRING.equals(literal.getDatatype())) {
+ if (QueryEvaluationUtility.isSimpleLiteral(literal) || XSD.STRING.equals(literal.getDatatype())) {
String lexValue = literal.getLabel();
try {
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA512.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA512.java
index 6cc60cebbe2..caec1f63bf0 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA512.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/hash/SHA512.java
@@ -15,7 +15,7 @@
import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} SHA512, as defined in
@@ -39,7 +39,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
if (args[0] instanceof Literal) {
Literal literal = (Literal) args[0];
- if (QueryEvaluationUtil.isSimpleLiteral(literal) || XSD.STRING.equals(literal.getDatatype())) {
+ if (QueryEvaluationUtility.isSimpleLiteral(literal) || XSD.STRING.equals(literal.getDatatype())) {
String lexValue = literal.getLabel();
try {
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Rand.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Rand.java
index ec5dbbcc63d..f3339f1aca5 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Rand.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/numeric/Rand.java
@@ -7,8 +7,6 @@
*******************************************************************************/
package org.eclipse.rdf4j.query.algebra.evaluation.function.numeric;
-import java.util.Random;
-
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.ValueFactory;
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrDt.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrDt.java
index 50e07e08b55..22b0ee10660 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrDt.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrDt.java
@@ -13,7 +13,7 @@
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} STRDT, as defined in
@@ -37,7 +37,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
Value lexicalValue = args[0];
Value datatypeValue = args[1];
- if (QueryEvaluationUtil.isSimpleLiteral(lexicalValue)) {
+ if (QueryEvaluationUtility.isSimpleLiteral(lexicalValue)) {
Literal lit = (Literal) lexicalValue;
if (datatypeValue instanceof IRI) {
return valueFactory.createLiteral(lit.getLabel(), (IRI) datatypeValue);
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrLang.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrLang.java
index 52b440a293a..56865d59f2a 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrLang.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/rdfterm/StrLang.java
@@ -12,7 +12,7 @@
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} STRLANG, as defined in
@@ -36,7 +36,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
Value lexicalValue = args[0];
Value languageValue = args[1];
- if (QueryEvaluationUtil.isSimpleLiteral(lexicalValue)) {
+ if (QueryEvaluationUtility.isSimpleLiteral(lexicalValue)) {
Literal lit = (Literal) lexicalValue;
if (languageValue instanceof Literal) {
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Concat.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Concat.java
index 4957908e45e..149bf074272 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Concat.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Concat.java
@@ -14,7 +14,7 @@
import org.eclipse.rdf4j.model.vocabulary.FN;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} CONCAT, as defined in
@@ -43,7 +43,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
if (arg instanceof Literal) {
Literal lit = (Literal) arg;
- if (!QueryEvaluationUtil.isStringLiteral(lit)) {
+ if (!QueryEvaluationUtility.isStringLiteral(lit)) {
throw new ValueExprEvaluationException("unexpected datatype for CONCAT operand: " + lit);
}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Contains.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Contains.java
index 04e30e48ced..5cb0ee4bc94 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Contains.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Contains.java
@@ -14,7 +14,7 @@
import org.eclipse.rdf4j.model.vocabulary.FN;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} CONTAINS, as defined in
@@ -51,8 +51,8 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
} else {
throw new ValueExprEvaluationException("incompatible operands for CONTAINS function");
}
- } else if (QueryEvaluationUtil.isStringLiteral(leftLit)) {
- if (QueryEvaluationUtil.isStringLiteral(rightLit)) {
+ } else if (QueryEvaluationUtility.isStringLiteral(leftLit)) {
+ if (QueryEvaluationUtility.isStringLiteral(rightLit)) {
String leftLexVal = leftLit.getLabel();
String rightLexVal = rightLit.getLabel();
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/EncodeForUri.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/EncodeForUri.java
index 41109ea2e97..32d2350ab91 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/EncodeForUri.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/EncodeForUri.java
@@ -15,7 +15,7 @@
import org.eclipse.rdf4j.model.vocabulary.FN;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} ENCODE_FOR_URI, as defined in
@@ -40,7 +40,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
if (args[0] instanceof Literal) {
Literal literal = (Literal) args[0];
- if (QueryEvaluationUtil.isStringLiteral(literal)) {
+ if (QueryEvaluationUtility.isStringLiteral(literal)) {
String lexValue = literal.getLabel();
return valueFactory.createLiteral(encodeUri(lexValue));
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/LowerCase.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/LowerCase.java
index 7b27f7caa6a..58dbf82fb45 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/LowerCase.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/LowerCase.java
@@ -16,7 +16,7 @@
import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} LCASE, as defined in
@@ -41,7 +41,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
Literal literal = (Literal) args[0];
// LowerCase function accepts only string literals.
- if (QueryEvaluationUtil.isStringLiteral(literal)) {
+ if (QueryEvaluationUtility.isStringLiteral(literal)) {
String lexicalValue = literal.getLabel().toLowerCase();
Optional language = literal.getLanguage();
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Replace.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Replace.java
index 234c0d1f475..1250e633d58 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Replace.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Replace.java
@@ -17,7 +17,7 @@
import org.eclipse.rdf4j.model.vocabulary.FN;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} REPLACE, as defined in
@@ -47,21 +47,21 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
flags = (Literal) args[3];
}
- if (!QueryEvaluationUtil.isStringLiteral(arg)) {
+ if (!QueryEvaluationUtility.isStringLiteral(arg)) {
throw new ValueExprEvaluationException("incompatible operand for REPLACE: " + arg);
}
- if (!QueryEvaluationUtil.isSimpleLiteral(pattern)) {
+ if (!QueryEvaluationUtility.isSimpleLiteral(pattern)) {
throw new ValueExprEvaluationException("incompatible operand for REPLACE: " + pattern);
}
- if (!QueryEvaluationUtil.isSimpleLiteral(replacement)) {
+ if (!QueryEvaluationUtility.isSimpleLiteral(replacement)) {
throw new ValueExprEvaluationException("incompatible operand for REPLACE: " + replacement);
}
String flagString = null;
if (flags != null) {
- if (!QueryEvaluationUtil.isSimpleLiteral(flags)) {
+ if (!QueryEvaluationUtility.isSimpleLiteral(flags)) {
throw new ValueExprEvaluationException("incompatible operand for REPLACE: " + flags);
}
flagString = flags.getLabel();
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrAfter.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrAfter.java
index 29e739dba50..3d164b215a0 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrAfter.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrAfter.java
@@ -16,7 +16,7 @@
import org.eclipse.rdf4j.model.vocabulary.FN;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} STRAFTER, as defined in
@@ -44,7 +44,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
Literal leftLit = (Literal) leftArg;
Literal rightLit = (Literal) rightArg;
- if (QueryEvaluationUtil.compatibleArguments(leftLit, rightLit)) {
+ if (QueryEvaluationUtility.compatibleArguments(leftLit, rightLit)) {
String lexicalValue = leftLit.getLabel();
String substring = rightLit.getLabel();
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrBefore.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrBefore.java
index 312c2ce73fa..526adb5dc2a 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrBefore.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrBefore.java
@@ -16,7 +16,7 @@
import org.eclipse.rdf4j.model.vocabulary.FN;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} STRBEFORE, as defined in
@@ -44,7 +44,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
Literal leftLit = (Literal) leftArg;
Literal rightLit = (Literal) rightArg;
- if (QueryEvaluationUtil.compatibleArguments(leftLit, rightLit)) {
+ if (QueryEvaluationUtility.compatibleArguments(leftLit, rightLit)) {
Optional leftLanguage = leftLit.getLanguage();
IRI leftDt = leftLit.getDatatype();
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrEnds.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrEnds.java
index 76bc55fd8c9..7342197debb 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrEnds.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrEnds.java
@@ -14,7 +14,7 @@
import org.eclipse.rdf4j.model.vocabulary.FN;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} STRENDS, as defined in
@@ -42,7 +42,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
Literal leftLit = (Literal) leftVal;
Literal rightLit = (Literal) rightVal;
- if (QueryEvaluationUtil.compatibleArguments(leftLit, rightLit)) {
+ if (QueryEvaluationUtility.compatibleArguments(leftLit, rightLit)) {
String leftLexVal = leftLit.getLabel();
String rightLexVal = rightLit.getLabel();
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrLen.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrLen.java
index fca8e8eef7f..b6baa89adbb 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrLen.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrLen.java
@@ -14,7 +14,7 @@
import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} STRLEN, as defined in
@@ -40,7 +40,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
Literal literal = (Literal) argValue;
// strlen function accepts only string literals
- if (QueryEvaluationUtil.isStringLiteral(literal)) {
+ if (QueryEvaluationUtility.isStringLiteral(literal)) {
// TODO we jump through some hoops here to get an xsd:integer
// literal. Shouldn't createLiteral(int) return an xsd:integer
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrStarts.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrStarts.java
index 83dc96a8684..d4f2c8e2ba6 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrStarts.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/StrStarts.java
@@ -14,7 +14,7 @@
import org.eclipse.rdf4j.model.vocabulary.FN;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} STRSTARTS, as defined in
@@ -42,7 +42,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
Literal leftLit = (Literal) leftVal;
Literal rightLit = (Literal) rightVal;
- if (QueryEvaluationUtil.compatibleArguments(leftLit, rightLit)) {
+ if (QueryEvaluationUtility.compatibleArguments(leftLit, rightLit)) {
String leftLexVal = leftLit.getLabel();
String rightLexVal = rightLit.getLabel();
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Substring.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Substring.java
index 6a02fb4f0c9..d30606f93de 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Substring.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/Substring.java
@@ -18,7 +18,7 @@
import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} SUBSTR, as defined in
@@ -50,7 +50,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
Literal literal = (Literal) argValue;
// substr function accepts string literals only.
- if (QueryEvaluationUtil.isStringLiteral(literal)) {
+ if (QueryEvaluationUtility.isStringLiteral(literal)) {
String lexicalValue = literal.getLabel();
// determine start index.
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/UpperCase.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/UpperCase.java
index 8ef525d9853..3dc6d3df2f2 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/UpperCase.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/string/UpperCase.java
@@ -16,7 +16,7 @@
import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* The SPARQL built-in {@link Function} UCASE, as defined in
@@ -41,7 +41,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
Literal literal = (Literal) args[0];
// UpperCase function accepts only string literal
- if (QueryEvaluationUtil.isStringLiteral(literal)) {
+ if (QueryEvaluationUtility.isStringLiteral(literal)) {
String lexicalValue = literal.getLabel().toUpperCase();
Optional language = literal.getLanguage();
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/xsd/CastFunction.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/xsd/CastFunction.java
index f080a3cd8b9..bbb40db4aaf 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/xsd/CastFunction.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/xsd/CastFunction.java
@@ -15,7 +15,7 @@
import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.function.Function;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* Abstract superclass for {@link org.eclipse.rdf4j.query.algebra.evaluation.function.Function}s that cast an argument
@@ -42,7 +42,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
Literal literal = (Literal) args[0];
IRI datatype = literal.getDatatype();
- if (QueryEvaluationUtil.isStringLiteral(literal)) {
+ if (QueryEvaluationUtility.isStringLiteral(literal)) {
String lexicalValue = XMLDatatypeUtil.collapseWhiteSpace(literal.getLabel());
if (isValidForDatatype(lexicalValue)) {
return valueFactory.createLiteral(lexicalValue, getXsdDatatype());
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/xsd/StringCast.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/xsd/StringCast.java
index d4c4db12459..285eb2e8c1a 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/xsd/StringCast.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/function/xsd/StringCast.java
@@ -15,7 +15,7 @@
import org.eclipse.rdf4j.model.util.Literals;
import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* A {@link org.eclipse.rdf4j.query.algebra.evaluation.function.Function} that tries to cast its argument to an
@@ -39,7 +39,7 @@ public Literal evaluate(ValueFactory valueFactory, Value... args) throws ValueEx
// we override because unlike most other cast functions, xsd:string should not accept a language-tagged
// string literal.
- if (QueryEvaluationUtil.isSimpleLiteral(literal)) {
+ if (QueryEvaluationUtility.isSimpleLiteral(literal)) {
String lexicalValue = XMLDatatypeUtil.collapseWhiteSpace(literal.getLabel());
if (isValidForDatatype(lexicalValue)) {
return valueFactory.createLiteral(lexicalValue, getXsdDatatype());
@@ -63,7 +63,7 @@ protected Literal convert(ValueFactory valueFactory, Value value) throws ValueEx
Literal literal = (Literal) value;
IRI datatype = literal.getDatatype();
- if (QueryEvaluationUtil.isSimpleLiteral(literal)) {
+ if (QueryEvaluationUtility.isSimpleLiteral(literal)) {
return valueFactory.createLiteral(literal.getLabel(), XSD.STRING);
} else if (!Literals.isLanguageLiteral(literal)) {
if (XMLDatatypeUtil.isNumericDatatype(datatype) || datatype.equals(XSD.BOOLEAN)
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ArrayBindingBasedQueryEvaluationContext.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ArrayBindingBasedQueryEvaluationContext.java
index 44c49285f66..998a4ca29fc 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ArrayBindingBasedQueryEvaluationContext.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ArrayBindingBasedQueryEvaluationContext.java
@@ -169,4 +169,4 @@ public void meet(ExtensionElem node) throws QueryEvaluationException {
String[] varNamesArr = varNames.toArray(new String[0]);
return varNamesArr;
}
-}
\ No newline at end of file
+}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ExtensionQueryEvaluationStep.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ExtensionQueryEvaluationStep.java
index 185389eab50..0aa9670f6f6 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ExtensionQueryEvaluationStep.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ExtensionQueryEvaluationStep.java
@@ -36,4 +36,4 @@ public CloseableIteration evaluate(Binding
}
return new ExtensionIterator(result, consumer, context);
}
-}
\ No newline at end of file
+}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/FilterOptimizer.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/FilterOptimizer.java
index a25b857f928..d0b3417de2b 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/FilterOptimizer.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/FilterOptimizer.java
@@ -34,39 +34,39 @@
/**
* Optimizes a query model by pushing {@link Filter}s as far down in the model tree as possible.
- *
+ *
* To make the first optimization succeed more often it splits filters which contains {@link And} conditions.
- *
+ *
*
* SELECT * WHERE {
- * ?s ?p ?o .
- * ?s ?p ?o2 .
- * FILTER(?o > '2'^^xsd:int && ?o2 < '4'^^xsd:int)
+ * ?s ?p ?o .
+ * ?s ?p ?o2 .
+ * FILTER(?o > '2'^^xsd:int && ?o2 < '4'^^xsd:int)
* }
*
May be more efficient when decomposed into
* SELECT * WHERE {
* ?s ?p ?o .
- * FILTER(?o > '2'^^xsd:int)
- * ?s ?p ?o2 .
- * FILTER(?o2 < '4'^^xsd:int)
+ * FILTER(?o > '2'^^xsd:int)
+ * ?s ?p ?o2 .
+ * FILTER(?o2 < '4'^^xsd:int)
* }
*
- *
+ *
* Then it optimizes a query model by merging adjacent {@link Filter}s. e.g.
* SELECT * WHERE {
* ?s ?p ?o .
* FILTER(?o > 2) .
* FILTER(?o < 4) .
- * }
- *
may be merged into
+ * }
+ *
may be merged into
* SELECT * WHERE {
- * ?s ?p ?o .
+ * ?s ?p ?o .
* FILTER(?o > 2 && ?o < 4) . }
*
- *
+ *
* This optimization allows for sharing evaluation costs in the future and removes an iterator. This is done as a second
* step to not break the first optimization. In the case that the splitting was done but did not help it is now undone.
- *
+ *
* @author Arjohn Kampman
* @author Jerven Bolleman
*/
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ParentReferenceCleaner.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ParentReferenceCleaner.java
index e7694541498..749b5c2f961 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ParentReferenceCleaner.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ParentReferenceCleaner.java
@@ -1,9 +1,9 @@
-/*******************************************************************************
- * Copyright (c) 2021 Eclipse RDF4J contributors.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Distribution License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
+/*******************************************************************************
+ * Copyright (c) 2021 Eclipse RDF4J contributors.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Distribution License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
*******************************************************************************/
package org.eclipse.rdf4j.query.algebra.evaluation.impl;
@@ -21,7 +21,7 @@
/**
* Cleans up {@link QueryModelNode#getParentNode()} references that have become inconsistent with the actual algebra
* tree structure due to optimization operations. Typically used at the very end of the optimization pipeline.
- *
+ *
* @author Jeen Broekstra
*/
public class ParentReferenceCleaner implements QueryOptimizer {
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ProjectionRemovalOptimizer.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ProjectionRemovalOptimizer.java
index a8ddfd7da81..9e6aed6157d 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ProjectionRemovalOptimizer.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ProjectionRemovalOptimizer.java
@@ -26,16 +26,16 @@
* SELECT ?s ?p ?o
* WHERE {?s ?p ?o }
*
Does not need a projection as the inner statement pattern returns the same result.
- *
+ *
* While
- * * SELECT ?s ?p
+ * * SELECT ?s ?p
* WHERE {?s ?p ?o }
*
Does as the statement pattern has one more variable in use than the projection.
- *
+ *
* Note: this optimiser should run after optimisations ran that depend on Projections. e.g.
- *
+ *
* @see UnionScopeChangeOptimizer
- *
+ *
* @author Jerven Bolleman
*/
public class ProjectionRemovalOptimizer implements QueryOptimizer {
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryEvaluationContext.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryEvaluationContext.java
index a3267bdcb83..0926388eee0 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryEvaluationContext.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryEvaluationContext.java
@@ -23,10 +23,10 @@
/**
* A QueryEvaluationContext stores values and methods that are valid throughout the lifetime of a query execution.
- *
+ *
* A classic case is the case of NOW() evaluation to the same instant for all invocations of that function in one query
* evaluation.
- *
+ *
*/
public interface QueryEvaluationContext {
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelNormalizer.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelNormalizer.java
index e80be9e31a5..f67b98e3b95 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelNormalizer.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelNormalizer.java
@@ -28,8 +28,7 @@
import org.eclipse.rdf4j.query.algebra.ValueConstant;
import org.eclipse.rdf4j.query.algebra.ValueExpr;
import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer;
-import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor;
import org.eclipse.rdf4j.query.algebra.helpers.VarNameCollector;
@@ -112,14 +111,11 @@ public void meet(LeftJoin leftJoin) {
} else if (rightArg instanceof SingletonSet) {
leftJoin.replaceWith(leftArg);
} else if (condition instanceof ValueConstant) {
- boolean conditionValue;
- try {
- conditionValue = QueryEvaluationUtil.getEffectiveBooleanValue(((ValueConstant) condition).getValue());
- } catch (ValueExprEvaluationException e) {
- conditionValue = false;
- }
+ boolean conditionValue = QueryEvaluationUtility
+ .getEffectiveBooleanValue(((ValueConstant) condition).getValue())
+ .orElse(false);
- if (conditionValue == false) {
+ if (!conditionValue) {
// Constraint is always false
leftJoin.replaceWith(leftArg);
} else {
@@ -189,14 +185,11 @@ public void meet(Filter node) {
if (arg instanceof EmptySet) {
// see #meetUnaryTupleOperator
} else if (condition instanceof ValueConstant) {
- boolean conditionValue;
- try {
- conditionValue = QueryEvaluationUtil.getEffectiveBooleanValue(((ValueConstant) condition).getValue());
- } catch (ValueExprEvaluationException e) {
- conditionValue = false;
- }
+ boolean conditionValue = QueryEvaluationUtility
+ .getEffectiveBooleanValue(((ValueConstant) condition).getValue())
+ .orElse(false);
- if (conditionValue == false) {
+ if (!conditionValue) {
// Constraint is always false
node.replaceWith(new EmptySet());
} else {
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelPruner.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelPruner.java
index a9da5c31521..bfd19a07da7 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelPruner.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/QueryModelPruner.java
@@ -20,8 +20,7 @@
import org.eclipse.rdf4j.query.algebra.ValueConstant;
import org.eclipse.rdf4j.query.algebra.ValueExpr;
import org.eclipse.rdf4j.query.algebra.evaluation.QueryOptimizer;
-import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor;
/**
@@ -80,15 +79,11 @@ public void meet(LeftJoin leftJoin) {
} else if (rightArg instanceof SingletonSet) {
leftJoin.replaceWith(leftArg);
} else if (condition instanceof ValueConstant) {
- boolean conditionValue;
- try {
- conditionValue = QueryEvaluationUtil
- .getEffectiveBooleanValue(((ValueConstant) condition).getValue());
- } catch (ValueExprEvaluationException e) {
- conditionValue = false;
- }
+ boolean conditionValue = QueryEvaluationUtility
+ .getEffectiveBooleanValue(((ValueConstant) condition).getValue())
+ .orElse(false);
- if (conditionValue == false) {
+ if (!conditionValue) {
// Constraint is always false
leftJoin.replaceWith(leftArg);
} else {
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/StrictEvaluationStrategy.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/StrictEvaluationStrategy.java
index ab7345c5bfc..068d025ed2d 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/StrictEvaluationStrategy.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/StrictEvaluationStrategy.java
@@ -27,11 +27,10 @@
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Triple;
import org.eclipse.rdf4j.model.Value;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
import org.eclipse.rdf4j.model.impl.BooleanLiteral;
import org.eclipse.rdf4j.model.util.Literals;
-import org.eclipse.rdf4j.model.vocabulary.RDF;
-import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.Dataset;
import org.eclipse.rdf4j.query.MutableBindingSet;
@@ -143,6 +142,7 @@
import org.eclipse.rdf4j.query.algebra.evaluation.util.MathUtil;
import org.eclipse.rdf4j.query.algebra.evaluation.util.OrderComparator;
import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
import org.eclipse.rdf4j.query.algebra.evaluation.util.ValueComparator;
import org.eclipse.rdf4j.query.impl.EmptyBindingSet;
import org.eclipse.rdf4j.util.UUIDable;
@@ -1068,7 +1068,7 @@ protected QueryValueEvaluationStep prepare(Var var, QueryEvaluationContext conte
@Override
public Value evaluate(BindingSet bindings)
- throws ValueExprEvaluationException, QueryEvaluationException {
+ throws QueryEvaluationException {
Value value = getValue.apply(bindings);
if (value == null) {
throw new ValueExprEvaluationException();
@@ -1128,7 +1128,7 @@ public Value evaluate(Str node, BindingSet bindings) throws QueryEvaluationExcep
} else if (argValue instanceof Literal) {
Literal literal = (Literal) argValue;
- if (QueryEvaluationUtil.isSimpleLiteral(literal)) {
+ if (QueryEvaluationUtility.isSimpleLiteral(literal)) {
return literal;
} else {
return tripleSource.getValueFactory().createLiteral(literal.getLabel());
@@ -1149,7 +1149,7 @@ public Value evaluate(Label node, BindingSet bindings)
if (argValue instanceof Literal) {
Literal literal = (Literal) argValue;
- if (QueryEvaluationUtil.isSimpleLiteral(literal)) {
+ if (QueryEvaluationUtility.isSimpleLiteral(literal)) {
return literal;
} else {
return tripleSource.getValueFactory().createLiteral(literal.getLabel());
@@ -1184,10 +1184,10 @@ public Value evaluate(Datatype node, BindingSet bindings)
// literal with datatype
return literal.getDatatype();
} else if (literal.getLanguage().isPresent()) {
- return RDF.LANGSTRING;
+ return CoreDatatype.RDF.LANGSTRING.getIri();
} else {
// simple literal
- return XSD.STRING;
+ return CoreDatatype.XSD.STRING.getIri();
}
}
@@ -1271,7 +1271,8 @@ public Value evaluate(IsLiteral node, BindingSet bindings)
/**
* Determines whether the operand (a variable) contains a numeric datatyped literal, i.e. a literal with datatype
- * xsd:float, xsd:double, xsd:decimal, or a derived datatype of xsd:decimal.
+ * CoreDatatype.XSD:float, CoreDatatype.XSD:double, CoreDatatype.XSD:decimal, or a derived datatype of
+ * CoreDatatype.XSD:decimal.
*
* @return true if the operand contains a numeric datatyped literal, false otherwise.
*/
@@ -1373,7 +1374,8 @@ protected QueryValueEvaluationStep prepare(LangMatches node, QueryEvaluationCont
}
private Value evaluateLangMatch(Value langTagValue, Value langRangeValue) {
- if (QueryEvaluationUtil.isSimpleLiteral(langTagValue) && QueryEvaluationUtil.isSimpleLiteral(langRangeValue)) {
+ if (QueryEvaluationUtility.isSimpleLiteral(langTagValue)
+ && QueryEvaluationUtility.isSimpleLiteral(langRangeValue)) {
String langTag = ((Literal) langTagValue).getLabel();
String langRange = ((Literal) langRangeValue).getLabel();
@@ -1529,8 +1531,9 @@ public QueryValueEvaluationStep prepare(FunctionCall node, QueryEvaluationContex
boolean allConstant = true;
for (int i = 0; i < args.size(); i++) {
argSteps[i] = precompile(args.get(i), context);
- if (!argSteps[i].isConstant())
+ if (!argSteps[i].isConstant()) {
allConstant = false;
+ }
}
if (allConstant) {
Value[] argValues = evaluateAllArguments(args, argSteps, EmptyBindingSet.getInstance());
@@ -1541,7 +1544,7 @@ public QueryValueEvaluationStep prepare(FunctionCall node, QueryEvaluationContex
@Override
public Value evaluate(BindingSet bindings)
- throws ValueExprEvaluationException, QueryEvaluationException {
+ throws QueryEvaluationException {
Value[] argValues = evaluateAllArguments(args, argSteps, bindings);
return function.evaluate(tripleSource, argValues);
}
@@ -1562,7 +1565,7 @@ private Value[] evaluateAllArguments(List args, QueryValueEvaluationS
public Value evaluate(And node, BindingSet bindings) throws QueryEvaluationException {
try {
Value leftValue = evaluate(node.getLeftArg(), bindings);
- if (!QueryEvaluationUtil.getEffectiveBooleanValue(leftValue)) {
+ if (QueryEvaluationUtility.getEffectiveBooleanValue(leftValue) == QueryEvaluationUtility.Result._false) {
// Left argument evaluates to false, we don't need to look any
// further
return BooleanLiteral.FALSE;
@@ -1571,7 +1574,7 @@ public Value evaluate(And node, BindingSet bindings) throws QueryEvaluationExcep
// Failed to evaluate the left argument. Result is 'false' when
// the right argument evaluates to 'false', failure otherwise.
Value rightValue = evaluate(node.getRightArg(), bindings);
- if (!QueryEvaluationUtil.getEffectiveBooleanValue(rightValue)) {
+ if (QueryEvaluationUtility.getEffectiveBooleanValue(rightValue) == QueryEvaluationUtility.Result._false) {
return BooleanLiteral.FALSE;
} else {
throw new ValueExprEvaluationException();
@@ -1633,7 +1636,7 @@ public Value evaluate(Now node, BindingSet bindings) throws QueryEvaluationExcep
/**
* During the execution of a single query NOW() should always return the same result and is in practical terms a
* constant during evaluation.
- *
+ *
* @param node that represent the NOW() function
* @param context that holds the shared now() of the query invocation
* @return a constant value evaluation step
@@ -1867,21 +1870,13 @@ public Value evaluate(Exists node, BindingSet bindings)
@Override
public boolean isTrue(ValueExpr expr, BindingSet bindings) throws QueryEvaluationException {
- try {
- Value value = evaluate(expr, bindings);
- return QueryEvaluationUtil.getEffectiveBooleanValue(value);
- } catch (ValueExprEvaluationException e) {
- return false;
- }
+ Value value = evaluate(expr, bindings);
+ return QueryEvaluationUtility.getEffectiveBooleanValue(value).orElse(false);
}
public boolean isTrue(QueryValueEvaluationStep expr, BindingSet bindings) throws QueryEvaluationException {
- try {
- Value value = expr.evaluate(bindings);
- return QueryEvaluationUtil.getEffectiveBooleanValue(value);
- } catch (ValueExprEvaluationException e) {
- return false;
- }
+ Value value = expr.evaluate(bindings);
+ return QueryEvaluationUtility.getEffectiveBooleanValue(value).orElse(false);
}
protected boolean isReducedOrDistinct(QueryModelNode node) {
@@ -2054,7 +2049,7 @@ public void setTrackTime(boolean trackTime) {
/**
* Supply a QueryValueEvalationStep that will invoke the function (operator passed in). It will try to optimise
* constant argument to be called only once per query run,
- *
+ *
* @param node the node to evaluate
* @param operation the function that wraps the operator.
* @param context in which the query is running.
@@ -2075,7 +2070,7 @@ protected QueryValueEvaluationStep supplyBinaryValueEvaluation(BinaryValueOperat
@Override
public Value evaluate(BindingSet bindings)
- throws ValueExprEvaluationException, QueryEvaluationException {
+ throws QueryEvaluationException {
Value rightVal = rightStep.evaluate(bindings);
return operation.apply(leftVal, rightVal);
}
@@ -2086,7 +2081,7 @@ public Value evaluate(BindingSet bindings)
@Override
public Value evaluate(BindingSet bindings)
- throws ValueExprEvaluationException, QueryEvaluationException {
+ throws QueryEvaluationException {
Value leftVal = leftStep.evaluate(bindings);
Value result = operation.apply(leftVal, rightVal);
return result;
@@ -2097,7 +2092,7 @@ public Value evaluate(BindingSet bindings)
@Override
public Value evaluate(BindingSet bindings)
- throws ValueExprEvaluationException, QueryEvaluationException {
+ throws QueryEvaluationException {
Value leftVal = leftStep.evaluate(bindings);
Value rightVal = rightStep.evaluate(bindings);
return operation.apply(leftVal, rightVal);
@@ -2108,7 +2103,7 @@ public Value evaluate(BindingSet bindings)
/**
* Return a QueryEvaluationStep that applies constant propegation.
- *
+ *
* @param node that will be evaluated/prepared
* @param operation the task to be done
* @param context in which the evaluation takes place
@@ -2126,7 +2121,7 @@ protected QueryValueEvaluationStep supplyUnaryValueEvaluation(UnaryValueOperator
@Override
public Value evaluate(BindingSet bindings)
- throws ValueExprEvaluationException, QueryEvaluationException {
+ throws QueryEvaluationException {
Value argValue = argStep.evaluate(bindings);
return operation.apply(argValue);
}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/BindingSetAssignmentQueryEvaluationStep.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/BindingSetAssignmentQueryEvaluationStep.java
index 4dde71ae336..bd701a3a97c 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/BindingSetAssignmentQueryEvaluationStep.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/BindingSetAssignmentQueryEvaluationStep.java
@@ -78,4 +78,4 @@ protected BindingSet getNextElement() throws QueryEvaluationException {
return result;
}
-}
\ No newline at end of file
+}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/IntersectionQueryEvaluationStep.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/IntersectionQueryEvaluationStep.java
index ffcf22dd17c..fec34d81181 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/IntersectionQueryEvaluationStep.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/IntersectionQueryEvaluationStep.java
@@ -36,4 +36,4 @@ public IntersectionQueryEvaluationStep(QueryEvaluationStep leftArg, QueryEvaluat
public CloseableIteration evaluate(BindingSet bs) {
return new IntersectIteration<>(leftArgDelayed.evaluate(bs), rightArgDelayed.evaluate(bs), setMaker);
}
-}
\ No newline at end of file
+}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/LeftJoinQueryEvaluationStep.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/LeftJoinQueryEvaluationStep.java
index d83d702ad14..ef7c222e183 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/LeftJoinQueryEvaluationStep.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/LeftJoinQueryEvaluationStep.java
@@ -89,4 +89,4 @@ public CloseableIteration evaluate(Binding
return new BadlyDesignedLeftJoinIterator(left, right, condition, bindings, problemVars);
}
}
-}
\ No newline at end of file
+}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/OrderQueryEvaluationStep.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/OrderQueryEvaluationStep.java
index bc9a9167c0b..de1671bc1a4 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/OrderQueryEvaluationStep.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/OrderQueryEvaluationStep.java
@@ -37,4 +37,4 @@ public OrderQueryEvaluationStep(Comparator cmp, long limit, boolean
public CloseableIteration evaluate(BindingSet bs) {
return new OrderIterator(preparedArg.evaluate(bs), cmp, limit, reduced, iterationCacheSyncThreshold);
}
-}
\ No newline at end of file
+}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/RegexValueEvaluationStepSupplier.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/RegexValueEvaluationStepSupplier.java
index 140a5872021..28346606582 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/RegexValueEvaluationStepSupplier.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/RegexValueEvaluationStepSupplier.java
@@ -21,7 +21,7 @@
import org.eclipse.rdf4j.query.algebra.evaluation.QueryValueEvaluationStep.ConstantQueryValueEvaluationStep;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryEvaluationContext;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
import org.eclipse.rdf4j.query.impl.EmptyBindingSet;
public class RegexValueEvaluationStepSupplier {
@@ -51,8 +51,8 @@ public Value evaluate(BindingSet bindings)
farg = strategy.evaluate(flagsArg, bindings);
}
- if (QueryEvaluationUtil.isStringLiteral(arg) && QueryEvaluationUtil.isSimpleLiteral(parg)
- && (farg == null || QueryEvaluationUtil.isSimpleLiteral(farg))) {
+ if (QueryEvaluationUtility.isStringLiteral(arg) && QueryEvaluationUtility.isSimpleLiteral(parg)
+ && (farg == null || QueryEvaluationUtility.isSimpleLiteral(farg))) {
String text = ((Literal) arg).getLabel();
String ptn = ((Literal) parg).getLabel();
// TODO should this Pattern be cached?
@@ -91,8 +91,8 @@ private static QueryValueEvaluationStep regexAndFlagsAreConstant(QueryValueEvalu
if (flagsArg != null) {
farg = fargStep.evaluate(EmptyBindingSet.getInstance());
}
- if (QueryEvaluationUtil.isSimpleLiteral(parg)
- && (farg == null || QueryEvaluationUtil.isSimpleLiteral(farg))) {
+ if (QueryEvaluationUtility.isSimpleLiteral(parg)
+ && (farg == null || QueryEvaluationUtility.isSimpleLiteral(farg))) {
String ptn = ((Literal) parg).getLabel();
int f = extractRegexFlags(farg);
Pattern pattern = Pattern.compile(ptn, f);
@@ -103,7 +103,7 @@ private static QueryValueEvaluationStep regexAndFlagsAreConstant(QueryValueEvalu
public Value evaluate(BindingSet bindings)
throws ValueExprEvaluationException, QueryEvaluationException {
Value arg = argStep.evaluate(bindings);
- if (QueryEvaluationUtil.isStringLiteral(arg)) {
+ if (QueryEvaluationUtility.isStringLiteral(arg)) {
String text = ((Literal) arg).getLabel();
boolean result = pattern.matcher(text).find();
BooleanLiteral valueOf = BooleanLiteral.valueOf(result);
@@ -125,8 +125,8 @@ private static QueryValueEvaluationStep allRegexPartsAreConstant(QueryValueEvalu
if (flagsArg != null) {
farg = fargStep.evaluate(EmptyBindingSet.getInstance());
}
- if (QueryEvaluationUtil.isStringLiteral(arg) && QueryEvaluationUtil.isSimpleLiteral(parg)
- && (farg == null || QueryEvaluationUtil.isSimpleLiteral(farg))) {
+ if (QueryEvaluationUtility.isStringLiteral(arg) && QueryEvaluationUtility.isSimpleLiteral(parg)
+ && (farg == null || QueryEvaluationUtility.isSimpleLiteral(farg))) {
String text = ((Literal) arg).getLabel();
String ptn = ((Literal) parg).getLabel();
int f = extractRegexFlags(farg);
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/ServiceQueryEvaluationStep.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/ServiceQueryEvaluationStep.java
index 22b29bcfb89..15720b1bd26 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/ServiceQueryEvaluationStep.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/ServiceQueryEvaluationStep.java
@@ -116,4 +116,4 @@ public void meet(Var var) {
}
}
-}
\ No newline at end of file
+}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/StatementPatternQueryEvaluationStep.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/StatementPatternQueryEvaluationStep.java
index f24ded5e41d..6675a1ddf42 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/StatementPatternQueryEvaluationStep.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/evaluationsteps/StatementPatternQueryEvaluationStep.java
@@ -276,7 +276,7 @@ private static Predicate subjectVariableHasEquals(boolean subEqPredVa
}
/**
- *
+ *
* @param statementPattern
* @param contextValue
* @return the contexts that are valid for this statement pattern or null
@@ -348,7 +348,7 @@ private static Resource[] fillContextsFromDatasSetGraphs(Set graphs) {
/**
* Converts statements into the required bindingsets. A lot of work is done in the constructor and then uses
* invokedynamic code with lambdas for the actual conversion.
- *
+ *
* This allows avoiding of significant work during the iteration. Which pays of if the iteration is long, otherwise
* it of course is an unneeded expense.
*/
@@ -383,10 +383,10 @@ protected BindingSet convert(Statement st) {
/**
* We are going to chain biconsumer functions allowing us to avoid a lot of equals etc. code
- *
+ *
* We need to test every binding with hasBinding etc. as these are not guaranteed to be equivalent between calls of
* evaluate(bs).
- *
+ *
* @return a converter from statement into MutableBindingSet
*/
private static BiConsumer makeConverter(QueryEvaluationContext context,
@@ -449,7 +449,7 @@ private static Predicate andThen(Predicate pred, Predicate
/**
* A convience function to chain the consumers together if one exists otherwise returns the new one.
- *
+ *
* @param co an earlier chain
* @param and the consumer to add to the chain
* @return a chain or the new (and) one
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/GroupIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/GroupIterator.java
index b28618d423e..5fdabf5262d 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/GroupIterator.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/GroupIterator.java
@@ -31,9 +31,9 @@
import org.eclipse.rdf4j.common.iteration.CloseableIteratorIteration;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Value;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
-import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.MutableBindingSet;
import org.eclipse.rdf4j.query.QueryEvaluationException;
@@ -169,7 +169,7 @@ private Set createSet(String setName) {
/**
* Only create a disk based set once the contents are large enough that it starts to pay off.
- *
+ *
* @param of the contents of the set.
*/
private class MemoryTillSizeXSet extends AbstractSet {
@@ -517,7 +517,7 @@ public BindingSet getPrototype() {
/**
* This is to collect together in operation an aggregate function the name of it. And the suppliers that will give
* the unique set and final value collectors per final binding set.
- *
+ *
* Making an aggregate function is quite a lot of work and we do not want to repeat that for each final binding.
*/
private class AggregatePredicateCollectorSupplier {
@@ -656,7 +656,7 @@ private class CountCollector implements AggregateCollector {
@Override
public Value getFinalValue() {
- return vf.createLiteral(Long.toString(value), XSD.INTEGER);
+ return vf.createLiteral(Long.toString(value), CoreDatatype.XSD.INTEGER);
}
}
@@ -670,7 +670,7 @@ public Value getFinalValue() {
}
private class IntegerCollector implements AggregateCollector {
- private Literal value = vf.createLiteral("0", XSD.INTEGER);
+ private Literal value = vf.createLiteral("0", CoreDatatype.XSD.INTEGER);
@Override
public Value getFinalValue() {
@@ -679,7 +679,7 @@ public Value getFinalValue() {
}
private class AvgCollector implements AggregateCollector {
- private Literal sum = vf.createLiteral("0", XSD.INTEGER);
+ private Literal sum = vf.createLiteral("0", CoreDatatype.XSD.INTEGER);
private long count;
private ValueExprEvaluationException typeError = null;
@@ -692,7 +692,7 @@ public Value getFinalValue() throws ValueExprEvaluationException {
}
if (count == 0) {
- return vf.createLiteral("0", XSD.INTEGER);
+ return vf.createLiteral("0", CoreDatatype.XSD.INTEGER);
}
Literal sizeLit = vf.createLiteral(count);
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinIterator.java
index 48b9f035e4a..4560f7d0f32 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinIterator.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/LeftJoinIterator.java
@@ -24,7 +24,7 @@
import org.eclipse.rdf4j.query.algebra.evaluation.QueryValueEvaluationStep;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryEvaluationContext;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
public class LeftJoinIterator extends LookAheadIteration {
@@ -139,12 +139,8 @@ protected BindingSet getNextElement() throws QueryEvaluationException {
}
private boolean isTrue(QueryValueEvaluationStep expr, QueryBindingSet bindings) {
- try {
- Value value = expr.evaluate(bindings);
- return QueryEvaluationUtil.getEffectiveBooleanValue(value);
- } catch (ValueExprEvaluationException e) {
- return false;
- }
+ Value value = expr.evaluate(bindings);
+ return QueryEvaluationUtility.getEffectiveBooleanValue(value).orElse(false);
}
@Override
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIterator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIterator.java
index 98aa89360e2..ce76b60278b 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIterator.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/iterator/OrderIterator.java
@@ -47,7 +47,7 @@ private static class SerializedQueue extends AbstractQue
private final File file;
- private ObjectOutputStream output;
+ private final ObjectOutputStream output;
private ObjectInputStream input;
@@ -134,9 +134,9 @@ public E next() {
@Override
public int size() {
if (next == null) {
- return (int) size;
+ return size;
} else {
- return (int) size + 1;
+ return size + 1;
}
}
@@ -277,17 +277,17 @@ protected Iteration createIteration() thro
while (iter.hasNext()) {
if (list.size() >= syncThreshold && list.size() < limit) {
SerializedQueue queue = new SerializedQueue<>("orderiter");
- sort(list).forEach(bs -> queue.add(bs));
+ sort(list).forEach(queue::add);
serialized.add(queue);
decrement(list.size() - queue.size());
list = new ArrayList<>(list.size());
- if (threshold == null && serialized.stream().mapToLong(q -> q.size()).sum() >= limit) {
- Stream stream = serialized.stream().map(q -> q.peekLast());
- threshold = stream.sorted(comparator).skip(serialized.size() - 1).findFirst().get();
+ if (threshold == null && serialized.stream().mapToLong(SerializedQueue::size).sum() >= limit) {
+ Stream stream = serialized.stream().map(SerializedQueue::peekLast);
+ threshold = stream.sorted(comparator).skip(serialized.size() - 1).findFirst().orElseThrow();
}
} else if (list.size() >= limit2 || !distinct && threshold == null && list.size() >= limit) {
List sorted = new ArrayList<>(limit2);
- sort(list).forEach(bs -> sorted.add(bs));
+ sort(list).forEach(sorted::add);
decrement(list.size() - sorted.size());
list = sorted;
if (sorted.size() >= limit) {
@@ -305,11 +305,17 @@ protected Iteration createIteration() thro
} finally {
iter.close();
}
- SortedIterators iterator;
+
List> iterators = new ArrayList<>(serialized.size() + 1);
- serialized.forEach(queue -> iterators.add(queue.iterator()));
+ serialized
+ .stream()
+ .map(SerializedQueue::iterator)
+ .forEach(iterators::add);
+
iterators.add(sort(list).iterator());
- iterator = new SortedIterators<>(comparator, distinct, iterators);
+
+ SortedIterators iterator = new SortedIterators<>(comparator, distinct, iterators);
+
return new LimitIteration<>(new CloseableIteratorIteration<>(iterator), limit);
}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java
index bd21d71d20c..794546c71e0 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java
@@ -10,12 +10,15 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryEvaluationException;
import org.eclipse.rdf4j.query.algebra.Order;
import org.eclipse.rdf4j.query.algebra.OrderElem;
+import org.eclipse.rdf4j.query.algebra.evaluation.ArrayBindingSet;
import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy;
import org.eclipse.rdf4j.query.algebra.evaluation.QueryValueEvaluationStep;
import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryEvaluationContext;
@@ -32,7 +35,7 @@
*/
public class OrderComparator implements Comparator {
- private final transient Logger logger = LoggerFactory.getLogger(OrderComparator.class);
+ private final static Logger logger = LoggerFactory.getLogger(OrderComparator.class);
private final ValueComparator cmp;
@@ -45,16 +48,12 @@ public OrderComparator(EvaluationStrategy strategy, Order order, ValueComparator
for (OrderElem element : order.getElements()) {
final QueryValueEvaluationStep prepared = strategy.precompile(element.getExpr(), context);
final boolean ascending = element.isAscending();
- Comparator comparator = new Comparator() {
+ Comparator comparator = (o1, o2) -> {
+ Value v1 = prepared.evaluate(o1);
+ Value v2 = prepared.evaluate(o2);
- @Override
- public int compare(BindingSet o1, BindingSet o2) {
- Value v1 = prepared.evaluate(o1);
- Value v2 = prepared.evaluate(o2);
-
- int compare = cmp.compare(v1, v2);
- return ascending ? compare : -compare;
- }
+ int compare = cmp.compare(v1, v2);
+ return ascending ? compare : -compare;
};
allComparator = andThen(allComparator, comparator);
}
@@ -75,7 +74,6 @@ private Comparator andThen(Comparator allComparator, Com
@Override
public int compare(BindingSet o1, BindingSet o2) {
-
try {
int comparedContents = bindingContentsComparator.compare(o1, o2);
if (comparedContents != 0) {
@@ -104,14 +102,24 @@ public int compare(BindingSet o1, BindingSet o2) {
// we create an ordered list of binding names (using natural string order) to use for
// consistent iteration over binding names and binding values.
- final ArrayList o1bindingNamesOrdered = new ArrayList<>(o1.getBindingNames());
- Collections.sort(o1bindingNamesOrdered);
+ List o1bindingNamesOrdered;
+ List o2bindingNamesOrdered;
+
+ if (o1 instanceof ArrayBindingSet && o2 instanceof ArrayBindingSet) {
+ o1bindingNamesOrdered = ((ArrayBindingSet) o1).getSortedBindingNames();
+ o2bindingNamesOrdered = ((ArrayBindingSet) o2).getSortedBindingNames();
+ } else {
+ o1bindingNamesOrdered = getSortedBindingNames(o1.getBindingNames());
+ o2bindingNamesOrdered = null;
+ }
// binding set sizes are equal. compare on binding names.
- if (!o1.getBindingNames().equals(o2.getBindingNames())) {
+ if ((o2bindingNamesOrdered != null && !sortedEquals(o1bindingNamesOrdered, o2bindingNamesOrdered))
+ || (!o1.getBindingNames().equals(o2.getBindingNames()))) {
- final ArrayList o2bindingNamesOrdered = new ArrayList<>(o2.getBindingNames());
- Collections.sort(o2bindingNamesOrdered);
+ if (o2bindingNamesOrdered == null) {
+ o2bindingNamesOrdered = getSortedBindingNames(o2.getBindingNames());
+ }
for (int i = 0; i < o1bindingNamesOrdered.size(); i++) {
String o1bn = o1bindingNamesOrdered.get(i);
@@ -140,4 +148,29 @@ public int compare(BindingSet o1, BindingSet o2) {
return 0;
}
}
+
+ private boolean sortedEquals(List o1bindingNamesOrdered, List o2bindingNamesOrdered) {
+ if (o1bindingNamesOrdered.size() != o2bindingNamesOrdered.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < o1bindingNamesOrdered.size(); i++) {
+ if (!o1bindingNamesOrdered.get(i).equals(o2bindingNamesOrdered.get(i))) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static List getSortedBindingNames(Set bindingNames) {
+ if (bindingNames.size() == 1) {
+ return Collections.singletonList(bindingNames.iterator().next());
+ }
+
+ ArrayList list = new ArrayList<>(bindingNames);
+ Collections.sort(list);
+ return list;
+ }
+
}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtil.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtil.java
index de8b21d7349..fe7a35361c8 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtil.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtil.java
@@ -7,18 +7,17 @@
*******************************************************************************/
package org.eclipse.rdf4j.query.algebra.evaluation.util;
-import java.util.Optional;
+import java.util.Objects;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.Duration;
import javax.xml.datatype.XMLGregorianCalendar;
-import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Value;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
import org.eclipse.rdf4j.model.util.Literals;
-import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.algebra.Compare.CompareOp;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
@@ -27,15 +26,29 @@
*/
public class QueryEvaluationUtil {
+ public static final ValueExprEvaluationException INDETERMINATE_DATE_TIME_EXCEPTION = new ValueExprEvaluationException(
+ "Indeterminate result for date/time comparison");
+ public static final ValueExprEvaluationException STRING_WITH_OTHER_SUPPORTED_TYPE_EXCEPTION = new ValueExprEvaluationException(
+ "Unable to compare strings with other supported types");
+ public static final ValueExprEvaluationException NUMERIC_WITH_OTHER_SUPPORTED_TYPE_EXCEPTION = new ValueExprEvaluationException(
+ "Unable to compare numeric types with other supported types");
+ public static final ValueExprEvaluationException DATE_WITH_OTHER_SUPPORTED_TYPE_EXCEPTION = new ValueExprEvaluationException(
+ "Unable to compare date types with other supported types");
+ public static final ValueExprEvaluationException UNSUPPOERTED_TYPES_EXCEPTION = new ValueExprEvaluationException(
+ "Unable to compare literals with unsupported types");
+ public static final ValueExprEvaluationException NOT_COMPATIBLE_AND_ORDERED_EXCEPTION = new ValueExprEvaluationException(
+ "Only literals with compatible, ordered datatypes can be compared using <, <=, > and >= operators");
+
/**
* Determines the effective boolean value (EBV) of the supplied value as defined in the
* SPARQL specification:
*
- * - The EBV of any literal whose type is xsd:boolean or numeric is false if the lexical form is not valid for
- * that datatype (e.g. "abc"^^xsd:integer).
- *
- If the argument is a typed literal with a datatype of xsd:boolean, the EBV is the value of that argument.
- *
- If the argument is a plain literal or a typed literal with a datatype of xsd:string, the EBV is false if the
- * operand value has zero length; otherwise the EBV is true.
+ *
- The EBV of any literal whose type is CoreDatatype.XSD:boolean or numeric is false if the lexical form is not
+ * valid for that datatype (e.g. "abc"^^xsd:integer).
+ *
- If the argument is a typed literal with a datatype of CoreDatatype.XSD:boolean, the EBV is the value of that
+ * argument.
+ *
- If the argument is a plain literal or a typed literal with a datatype of CoreDatatype.XSD:string, the EBV is
+ * false if the operand value has zero length; otherwise the EBV is true.
*
- If the argument is a numeric type or a typed literal with a datatype derived from a numeric type, the EBV is
* false if the operand value is NaN or is numerically equal to zero; otherwise the EBV is true.
*
- All other arguments, including unbound arguments, produce a type error.
@@ -46,31 +59,31 @@ public class QueryEvaluationUtil {
* @throws ValueExprEvaluationException In case the application of the EBV algorithm results in a type error.
*/
public static boolean getEffectiveBooleanValue(Value value) throws ValueExprEvaluationException {
- if (value instanceof Literal) {
+ if (value.isLiteral()) {
Literal literal = (Literal) value;
String label = literal.getLabel();
- IRI datatype = literal.getDatatype();
+ CoreDatatype.XSD datatype = literal.getCoreDatatype().asXSDDatatype().orElse(null);
- if (datatype.equals(XSD.STRING)) {
+ if (datatype == CoreDatatype.XSD.STRING) {
return label.length() > 0;
- } else if (datatype.equals(XSD.BOOLEAN)) {
+ } else if (datatype == CoreDatatype.XSD.BOOLEAN) {
// also false for illegal values
return "true".equals(label) || "1".equals(label);
- } else if (datatype.equals(XSD.DECIMAL)) {
+ } else if (datatype == CoreDatatype.XSD.DECIMAL) {
try {
String normDec = XMLDatatypeUtil.normalizeDecimal(label);
return !normDec.equals("0.0");
} catch (IllegalArgumentException e) {
return false;
}
- } else if (XMLDatatypeUtil.isIntegerDatatype(datatype)) {
+ } else if (datatype != null && datatype.isIntegerDatatype()) {
try {
String normInt = XMLDatatypeUtil.normalize(label, datatype);
return !normInt.equals("0");
} catch (IllegalArgumentException e) {
return false;
}
- } else if (XMLDatatypeUtil.isFloatingPointDatatype(datatype)) {
+ } else if (datatype != null && datatype.isFloatingPointDatatype()) {
try {
String normFP = XMLDatatypeUtil.normalize(label, datatype);
return !normFP.equals("0.0E0") && !normFP.equals("NaN");
@@ -78,6 +91,7 @@ public static boolean getEffectiveBooleanValue(Value value) throws ValueExprEval
return false;
}
}
+
}
throw new ValueExprEvaluationException();
@@ -90,16 +104,16 @@ public static boolean compare(Value leftVal, Value rightVal, CompareOp operator)
public static boolean compare(Value leftVal, Value rightVal, CompareOp operator, boolean strict)
throws ValueExprEvaluationException {
- if (leftVal instanceof Literal && rightVal instanceof Literal) {
+ if (leftVal.isLiteral() && rightVal.isLiteral()) {
// Both left and right argument is a Literal
return compareLiterals((Literal) leftVal, (Literal) rightVal, operator, strict);
} else {
// All other value combinations
switch (operator) {
case EQ:
- return valuesEqual(leftVal, rightVal);
+ return Objects.equals(leftVal, rightVal);
case NE:
- return !valuesEqual(leftVal, rightVal);
+ return !Objects.equals(leftVal, rightVal);
default:
throw new ValueExprEvaluationException(
"Only literals with compatible, ordered datatypes can be compared using <, <=, > and >= operators");
@@ -107,10 +121,6 @@ public static boolean compare(Value leftVal, Value rightVal, CompareOp operator,
}
}
- private static boolean valuesEqual(Value leftVal, Value rightVal) {
- return leftVal != null && rightVal != null && leftVal.equals(rightVal);
- }
-
/**
* Compares the supplied {@link Literal} arguments using the supplied operator, using strict (minimally-conforming)
* SPARQL 1.1 operator behavior.
@@ -144,123 +154,75 @@ public static boolean compareLiterals(Literal leftLit, Literal rightLit, Compare
// type precendence:
// - simple literal
// - numeric
- // - xsd:boolean
- // - xsd:dateTime
- // - xsd:string
+ // - CoreDatatype.XSD:boolean
+ // - CoreDatatype.XSD:dateTime
+ // - CoreDatatype.XSD:string
// - RDF term (equal and unequal only)
- IRI leftDatatype = leftLit.getDatatype();
- IRI rightDatatype = rightLit.getDatatype();
-
- XSD.Datatype leftXsdDatatype = Literals.getXsdDatatype(leftLit).orElse(null);
- XSD.Datatype rightXsdDatatype = Literals.getXsdDatatype(rightLit).orElse(null);
+ CoreDatatype.XSD leftCoreDatatype = leftLit.getCoreDatatype().asXSDDatatype().orElse(null);
+ CoreDatatype.XSD rightCoreDatatype = rightLit.getCoreDatatype().asXSDDatatype().orElse(null);
boolean leftLangLit = Literals.isLanguageLiteral(leftLit);
boolean rightLangLit = Literals.isLanguageLiteral(rightLit);
// for purposes of query evaluation in SPARQL, simple literals and string-typed literals with the same lexical
// value are considered equal.
- IRI commonDatatype = null;
- if (QueryEvaluationUtil.isSimpleLiteral(leftLit) && QueryEvaluationUtil.isSimpleLiteral(rightLit)) {
- commonDatatype = XSD.STRING;
- }
- Integer compareResult = null;
-
- if (QueryEvaluationUtil.isSimpleLiteral(leftLit) && QueryEvaluationUtil.isSimpleLiteral(rightLit)) {
- compareResult = leftLit.getLabel().compareTo(rightLit.getLabel());
- } else if ((!leftLangLit && !rightLangLit) || commonDatatype != null) {
- if (commonDatatype == null && (leftXsdDatatype != null && rightXsdDatatype != null)) {
- if (leftXsdDatatype == rightXsdDatatype || leftDatatype.equals(rightDatatype)) {
- commonDatatype = leftDatatype;
- } else if (leftXsdDatatype.isNumericDatatype() && rightXsdDatatype.isNumericDatatype()) {
- // left and right arguments have different datatypes, try to find a more general, shared datatype
- if (leftXsdDatatype == XSD.Datatype.DOUBLE || rightXsdDatatype == XSD.Datatype.DOUBLE) {
- commonDatatype = XSD.DOUBLE;
- } else if (leftXsdDatatype == XSD.Datatype.FLOAT || rightXsdDatatype == XSD.Datatype.FLOAT) {
- commonDatatype = XSD.FLOAT;
- } else if (leftXsdDatatype == XSD.Datatype.DECIMAL
- || rightXsdDatatype == XSD.Datatype.DECIMAL) {
- commonDatatype = XSD.DECIMAL;
- } else {
- commonDatatype = XSD.INTEGER;
- }
- } else if (!strict && leftXsdDatatype.isCalendarDatatype() && rightXsdDatatype.isCalendarDatatype()) {
- // We're not running in strict eval mode so we use extended datatype comparsion.
- commonDatatype = XSD.DATETIME;
- } else if (!strict && leftXsdDatatype.isDurationDatatype() && rightXsdDatatype.isDurationDatatype()) {
- commonDatatype = XSD.DURATION;
- }
- } else if (commonDatatype == null && (leftXsdDatatype == null || rightXsdDatatype == null)) {
- if (leftDatatype.equals(rightDatatype)) {
- commonDatatype = leftDatatype;
- } else if (XMLDatatypeUtil.isNumericDatatype(leftDatatype)
- && XMLDatatypeUtil.isNumericDatatype(rightDatatype)) {
- // left and right arguments have different datatypes, try to find a more general, shared datatype
- if (leftDatatype.equals(XSD.DOUBLE) || rightDatatype.equals(XSD.DOUBLE)) {
- commonDatatype = XSD.DOUBLE;
- } else if (leftDatatype.equals(XSD.FLOAT) || rightDatatype.equals(XSD.FLOAT)) {
- commonDatatype = XSD.FLOAT;
- } else if (leftDatatype.equals(XSD.DECIMAL) || rightDatatype.equals(XSD.DECIMAL)) {
- commonDatatype = XSD.DECIMAL;
- } else {
- commonDatatype = XSD.INTEGER;
- }
- } else if (!strict && XMLDatatypeUtil.isCalendarDatatype(leftDatatype)
- && XMLDatatypeUtil.isCalendarDatatype(rightDatatype)) {
- // We're not running in strict eval mode so we use extended datatype comparsion.
- commonDatatype = XSD.DATETIME;
- } else if (!strict && XMLDatatypeUtil.isDurationDatatype(leftDatatype)
- && XMLDatatypeUtil.isDurationDatatype(rightDatatype)) {
- commonDatatype = XSD.DURATION;
- }
- }
+ if (QueryEvaluationUtil.isSimpleLiteral(leftLangLit, leftCoreDatatype)
+ && QueryEvaluationUtil.isSimpleLiteral(rightLangLit, rightCoreDatatype)) {
+ return compareWithOperator(operator, leftLit.getLabel().compareTo(rightLit.getLabel()));
+ } else if (!(leftLangLit || rightLangLit)) {
+
+ CoreDatatype.XSD commonDatatype = getCommonDatatype(strict, leftCoreDatatype, rightCoreDatatype);
if (commonDatatype != null) {
try {
- if (commonDatatype.equals(XSD.DOUBLE)) {
- compareResult = Double.compare(leftLit.doubleValue(), rightLit.doubleValue());
- } else if (commonDatatype.equals(XSD.FLOAT)) {
- compareResult = Float.compare(leftLit.floatValue(), rightLit.floatValue());
- } else if (commonDatatype.equals(XSD.DECIMAL)) {
- compareResult = leftLit.decimalValue().compareTo(rightLit.decimalValue());
- } else if (XMLDatatypeUtil.isIntegerDatatype(commonDatatype)) {
- compareResult = leftLit.integerValue().compareTo(rightLit.integerValue());
- } else if (commonDatatype.equals(XSD.BOOLEAN)) {
- Boolean leftBool = leftLit.booleanValue();
- Boolean rightBool = rightLit.booleanValue();
- compareResult = leftBool.compareTo(rightBool);
- } else if (XMLDatatypeUtil.isCalendarDatatype(commonDatatype)) {
+ if (commonDatatype == CoreDatatype.XSD.DOUBLE) {
+ return compareWithOperator(operator,
+ Double.compare(leftLit.doubleValue(), rightLit.doubleValue()));
+ } else if (commonDatatype == CoreDatatype.XSD.FLOAT) {
+ return compareWithOperator(operator,
+ Float.compare(leftLit.floatValue(), rightLit.floatValue()));
+ } else if (commonDatatype == CoreDatatype.XSD.DECIMAL) {
+ return compareWithOperator(operator, leftLit.decimalValue().compareTo(rightLit.decimalValue()));
+ } else if (commonDatatype.isIntegerDatatype()) {
+ return compareWithOperator(operator, leftLit.integerValue().compareTo(rightLit.integerValue()));
+ } else if (commonDatatype == CoreDatatype.XSD.BOOLEAN) {
+ return compareWithOperator(operator,
+ Boolean.compare(leftLit.booleanValue(), rightLit.booleanValue()));
+ } else if (commonDatatype.isCalendarDatatype()) {
XMLGregorianCalendar left = leftLit.calendarValue();
XMLGregorianCalendar right = rightLit.calendarValue();
- compareResult = left.compare(right);
+ int compare = left.compare(right);
// Note: XMLGregorianCalendar.compare() returns compatible values (-1, 0, 1) but INDETERMINATE
// needs special treatment
- if (compareResult == DatatypeConstants.INDETERMINATE) {
- // If we compare two xsd:dateTime we should use the specific comparison specified in SPARQL
+ if (compare == DatatypeConstants.INDETERMINATE) {
+ // If we compare two CoreDatatype.XSD:dateTime we should use the specific comparison
+ // specified in SPARQL
// 1.1
- if ((leftXsdDatatype == XSD.Datatype.DATETIME
- || (leftXsdDatatype == null && leftDatatype.equals(XSD.DATETIME)))
- && (rightXsdDatatype == XSD.Datatype.DATETIME
- || (rightXsdDatatype == null && rightDatatype.equals(XSD.DATETIME)))) {
- throw new ValueExprEvaluationException("Indeterminate result for date/time comparison");
- } else {
- // We fallback to the regular RDF term compare
- compareResult = null;
+ if (leftCoreDatatype == CoreDatatype.XSD.DATETIME
+ && rightCoreDatatype == CoreDatatype.XSD.DATETIME) {
+ throw INDETERMINATE_DATE_TIME_EXCEPTION;
}
-
+ } else {
+ return compareWithOperator(operator, compare);
}
- } else if (!strict && XMLDatatypeUtil.isDurationDatatype(commonDatatype)) {
+
+ } else if (!strict && commonDatatype.isDurationDatatype()) {
Duration left = XMLDatatypeUtil.parseDuration(leftLit.getLabel());
Duration right = XMLDatatypeUtil.parseDuration(rightLit.getLabel());
- compareResult = left.compare(right);
- if (compareResult == DatatypeConstants.INDETERMINATE) {
- compareResult = null; // We fallback to regular term comparison
+ int compare = left.compare(right);
+ if (compare != DatatypeConstants.INDETERMINATE) {
+ return compareWithOperator(operator, compare);
+ } else {
+ return otherCases(leftLit, rightLit, operator, leftCoreDatatype, rightCoreDatatype,
+ leftLangLit, rightLangLit);
}
- } else if (commonDatatype.equals(XSD.STRING)) {
- compareResult = leftLit.getLabel().compareTo(rightLit.getLabel());
+
+ } else if (commonDatatype == CoreDatatype.XSD.STRING) {
+ return compareWithOperator(operator, leftLit.getLabel().compareTo(rightLit.getLabel()));
}
} catch (IllegalArgumentException e) {
// One of the basic-type method calls failed, try syntactic match before throwing an error
@@ -278,105 +240,116 @@ public static boolean compareLiterals(Literal leftLit, Literal rightLit, Compare
}
}
- if (compareResult != null) {
- // Literals have compatible ordered datatypes
- switch (operator) {
- case LT:
- return compareResult.intValue() < 0;
- case LE:
- return compareResult.intValue() <= 0;
- case EQ:
- return compareResult.intValue() == 0;
- case NE:
- return compareResult.intValue() != 0;
- case GE:
- return compareResult.intValue() >= 0;
- case GT:
- return compareResult.intValue() > 0;
- default:
- throw new IllegalArgumentException("Unknown operator: " + operator);
- }
- } else {
- // All other cases, e.g. literals with languages, unequal or
- // unordered datatypes, etc. These arguments can only be compared
- // using the operators 'EQ' and 'NE'. See SPARQL's RDFterm-equal
- // operator
+ // All other cases, e.g. literals with languages, unequal or
+ // unordered datatypes, etc. These arguments can only be compared
+ // using the operators 'EQ' and 'NE'. See SPARQL's RDFterm-equal
+ // operator
- boolean literalsEqual = leftLit.equals(rightLit);
+ return otherCases(leftLit, rightLit, operator, leftCoreDatatype, rightCoreDatatype, leftLangLit, rightLangLit);
- if (!literalsEqual) {
- if (!leftLangLit && !rightLangLit && isSupportedDatatype(leftDatatype)
- && isSupportedDatatype(rightDatatype)) {
- // left and right arguments have incompatible but supported datatypes
+ }
- // we need to check that the lexical-to-value mapping for both datatypes succeeds
- if (!XMLDatatypeUtil.isValidValue(leftLit.getLabel(), leftDatatype)) {
- throw new ValueExprEvaluationException("not a valid datatype value: " + leftLit);
- }
+ private static boolean otherCases(Literal leftLit, Literal rightLit, CompareOp operator,
+ CoreDatatype.XSD leftCoreDatatype, CoreDatatype.XSD rightCoreDatatype, boolean leftLangLit,
+ boolean rightLangLit) {
+ boolean literalsEqual = leftLit.equals(rightLit);
- if (!XMLDatatypeUtil.isValidValue(rightLit.getLabel(), rightDatatype)) {
- throw new ValueExprEvaluationException("not a valid datatype value: " + rightLit);
- }
+ if (!literalsEqual) {
+ if (!leftLangLit && !rightLangLit && isSupportedDatatype(leftCoreDatatype)
+ && isSupportedDatatype(rightCoreDatatype)) {
+ // left and right arguments have incompatible but supported datatypes
- boolean leftString;
- boolean rightString;
- boolean leftNumeric;
- boolean rightNumeric;
- boolean leftDate;
- boolean rightDate;
-
- if (leftXsdDatatype != null) {
- leftString = leftXsdDatatype == XSD.Datatype.STRING;
- leftNumeric = leftXsdDatatype.isNumericDatatype();
- leftDate = leftXsdDatatype.isCalendarDatatype();
- } else {
- leftString = leftDatatype.equals(XSD.STRING);
- leftNumeric = XMLDatatypeUtil.isNumericDatatype(leftDatatype);
- leftDate = XMLDatatypeUtil.isCalendarDatatype(leftDatatype);
- }
+ // we need to check that the lexical-to-value mapping for both datatypes succeeds
+ if (!XMLDatatypeUtil.isValidValue(leftLit.getLabel(), leftCoreDatatype)) {
+ throw new ValueExprEvaluationException("not a valid datatype value: " + leftLit);
+ }
- if (rightXsdDatatype != null) {
- rightString = rightXsdDatatype == XSD.Datatype.STRING;
- rightNumeric = rightXsdDatatype.isNumericDatatype();
- rightDate = rightXsdDatatype.isCalendarDatatype();
- } else {
- rightString = rightDatatype.equals(XSD.STRING);
- rightNumeric = XMLDatatypeUtil.isNumericDatatype(rightDatatype);
- rightDate = XMLDatatypeUtil.isCalendarDatatype(rightDatatype);
- }
+ if (!XMLDatatypeUtil.isValidValue(rightLit.getLabel(), rightCoreDatatype)) {
+ throw new ValueExprEvaluationException("not a valid datatype value: " + rightLit);
+ }
- if (leftString != rightString) {
- throw new ValueExprEvaluationException("Unable to compare strings with other supported types");
- }
- if (leftNumeric != rightNumeric) {
- throw new ValueExprEvaluationException(
- "Unable to compare numeric types with other supported types");
- }
- if (leftDate != rightDate) {
- throw new ValueExprEvaluationException(
- "Unable to compare date types with other supported types");
- }
- } else if (!leftLangLit && !rightLangLit) {
- // For literals with unsupported datatypes we don't know if their values are equal
- throw new ValueExprEvaluationException("Unable to compare literals with unsupported types");
+ boolean leftString = leftCoreDatatype == CoreDatatype.XSD.STRING;
+ boolean leftNumeric = leftCoreDatatype.isNumericDatatype();
+ boolean leftDate = leftCoreDatatype.isCalendarDatatype();
+
+ boolean rightString = rightCoreDatatype == CoreDatatype.XSD.STRING;
+ boolean rightNumeric = rightCoreDatatype.isNumericDatatype();
+ boolean rightDate = rightCoreDatatype.isCalendarDatatype();
+
+ if (leftString != rightString) {
+ throw STRING_WITH_OTHER_SUPPORTED_TYPE_EXCEPTION;
+ }
+ if (leftNumeric != rightNumeric) {
+ throw NUMERIC_WITH_OTHER_SUPPORTED_TYPE_EXCEPTION;
}
+ if (leftDate != rightDate) {
+ throw DATE_WITH_OTHER_SUPPORTED_TYPE_EXCEPTION;
+ }
+ } else if (!leftLangLit && !rightLangLit) {
+ // For literals with unsupported datatypes we don't know if their values are equal
+ throw UNSUPPOERTED_TYPES_EXCEPTION;
}
+ }
- switch (operator) {
- case EQ:
- return literalsEqual;
- case NE:
- return !literalsEqual;
- case LT:
- case LE:
- case GE:
- case GT:
- throw new ValueExprEvaluationException(
- "Only literals with compatible, ordered datatypes can be compared using <, <=, > and >= operators");
- default:
- throw new IllegalArgumentException("Unknown operator: " + operator);
+ switch (operator) {
+ case EQ:
+ return literalsEqual;
+ case NE:
+ return !literalsEqual;
+ case LT:
+ case LE:
+ case GE:
+ case GT:
+ throw NOT_COMPATIBLE_AND_ORDERED_EXCEPTION;
+ default:
+ throw new IllegalArgumentException("Unknown operator: " + operator);
+ }
+ }
+
+ private static CoreDatatype.XSD getCommonDatatype(boolean strict, CoreDatatype.XSD leftCoreDatatype,
+ CoreDatatype.XSD rightCoreDatatype) {
+ if (leftCoreDatatype != null && rightCoreDatatype != null) {
+ if (leftCoreDatatype == rightCoreDatatype) {
+ return leftCoreDatatype;
+ } else if (leftCoreDatatype.isNumericDatatype() && rightCoreDatatype.isNumericDatatype()) {
+ // left and right arguments have different datatypes, try to find a more general, shared datatype
+ if (leftCoreDatatype == CoreDatatype.XSD.DOUBLE || rightCoreDatatype == CoreDatatype.XSD.DOUBLE) {
+ return CoreDatatype.XSD.DOUBLE;
+ } else if (leftCoreDatatype == CoreDatatype.XSD.FLOAT || rightCoreDatatype == CoreDatatype.XSD.FLOAT) {
+ return CoreDatatype.XSD.FLOAT;
+ } else if (leftCoreDatatype == CoreDatatype.XSD.DECIMAL
+ || rightCoreDatatype == CoreDatatype.XSD.DECIMAL) {
+ return CoreDatatype.XSD.DECIMAL;
+ } else {
+ return CoreDatatype.XSD.INTEGER;
+ }
+ } else if (!strict && leftCoreDatatype.isCalendarDatatype() && rightCoreDatatype.isCalendarDatatype()) {
+ // We're not running in strict eval mode so we use extended datatype comparsion.
+ return CoreDatatype.XSD.DATETIME;
+ } else if (!strict && leftCoreDatatype.isDurationDatatype() && rightCoreDatatype.isDurationDatatype()) {
+ return CoreDatatype.XSD.DURATION;
}
}
+ return null;
+ }
+
+ private static boolean compareWithOperator(CompareOp operator, int i) {
+ switch (operator) {
+ case LT:
+ return i < 0;
+ case LE:
+ return i <= 0;
+ case EQ:
+ return i == 0;
+ case NE:
+ return i != 0;
+ case GE:
+ return i >= 0;
+ case GT:
+ return i > 0;
+ default:
+ throw new IllegalArgumentException("Unknown operator: " + operator);
+ }
}
/**
@@ -387,20 +360,22 @@ && isSupportedDatatype(rightDatatype)) {
* Documentation
*/
public static boolean isPlainLiteral(Value v) {
- if (v instanceof Literal) {
+ if (v.isLiteral()) {
return isPlainLiteral(((Literal) v));
}
return false;
}
public static boolean isPlainLiteral(Literal l) {
- Optional xsdDatatype = Literals.getXsdDatatype(l);
- return xsdDatatype
- .map(datatype -> datatype == XSD.Datatype.STRING)
- .orElseGet(() -> (l.getDatatype().equals(XSD.STRING)));
-
+ assert l.getLanguage().isEmpty() || (l.getCoreDatatype() == CoreDatatype.RDF.LANGSTRING);
+ return l.getCoreDatatype() == CoreDatatype.XSD.STRING || l.getCoreDatatype() == CoreDatatype.RDF.LANGSTRING;
}
+// public static boolean isPlainLiteral(Literal l) {
+// return l.getCoreDatatype().filter(d -> d == CoreDatatype.XSD.STRING).isPresent();
+//// return l.getCoreDatatype().orElse(null) == CoreDatatype.XSD.STRING;
+// }
+
/**
* Checks whether the supplied value is a "simple literal". A "simple literal" is a literal with no language tag nor
* datatype.
@@ -408,7 +383,7 @@ public static boolean isPlainLiteral(Literal l) {
* @see SPARQL Simple Literal Documentation
*/
public static boolean isSimpleLiteral(Value v) {
- if (v instanceof Literal) {
+ if (v.isLiteral()) {
return isSimpleLiteral((Literal) v);
}
@@ -417,22 +392,32 @@ public static boolean isSimpleLiteral(Value v) {
/**
* Checks whether the supplied literal is a "simple literal". A "simple literal" is a literal with no language tag
- * and the datatype {@link XSD#STRING}.
+ * and the datatype {@link CoreDatatype.XSD#STRING}.
*
* @see SPARQL Simple Literal Documentation
*/
public static boolean isSimpleLiteral(Literal l) {
- return !Literals.isLanguageLiteral(l) && l.getDatatype().equals(XSD.STRING);
+ return l.getCoreDatatype() == CoreDatatype.XSD.STRING && !Literals.isLanguageLiteral(l);
+ }
+
+ /**
+ * Checks whether the supplied literal is a "simple literal". A "simple literal" is a literal with no language tag
+ * and the datatype {@link CoreDatatype.XSD#STRING}.
+ *
+ * @see SPARQL Simple Literal Documentation
+ */
+ public static boolean isSimpleLiteral(boolean isLang, CoreDatatype datatype) {
+ return !isLang && datatype == CoreDatatype.XSD.STRING;
}
/**
* Checks whether the supplied literal is a "string literal". A "string literal" is either a simple literal, a plain
- * literal with language tag, or a literal with datatype xsd:string.
+ * literal with language tag, or a literal with datatype CoreDatatype.XSD:string.
*
* @see SPARQL Functions on Strings Documentation
*/
public static boolean isStringLiteral(Value v) {
- if (v instanceof Literal) {
+ if (v.isLiteral()) {
return isStringLiteral((Literal) v);
}
@@ -449,37 +434,30 @@ public static boolean isStringLiteral(Value v) {
* Rules
*/
public static boolean compatibleArguments(Literal arg1, Literal arg2) {
- boolean arg1Language = Literals.isLanguageLiteral(arg1);
- boolean arg2Language = Literals.isLanguageLiteral(arg2);
- boolean arg1Simple = isSimpleLiteral(arg1);
- boolean arg2Simple = isSimpleLiteral(arg2);
- // 1. The arguments are literals typed as xsd:string
+ // 1. The arguments are literals typed as CoreDatatype.XSD:string
// 2. The arguments are language literals with identical language tags
// 3. The first argument is a language literal and the second
- // argument is a literal typed as xsd:string
-
- boolean compatible =
-
- (arg1Simple && arg2Simple)
- || (arg1Language && arg2Language && arg1.getLanguage().equals(arg2.getLanguage()))
- || (arg1Language && arg2Simple);
+ // argument is a literal typed as CoreDatatype.XSD:string
- return compatible;
+ return (isSimpleLiteral(arg1) && isSimpleLiteral(arg2))
+ || (Literals.isLanguageLiteral(arg1) && Literals.isLanguageLiteral(arg2)
+ && arg1.getLanguage().equals(arg2.getLanguage()))
+ || (Literals.isLanguageLiteral(arg1) && isSimpleLiteral(arg2));
}
/**
* Checks whether the supplied literal is a "string literal". A "string literal" is either a simple literal, a plain
- * literal with language tag, or a literal with datatype xsd:string.
+ * literal with language tag, or a literal with datatype CoreDatatype.XSD:string.
*
* @see SPARQL Functions on Strings Documentation
*/
public static boolean isStringLiteral(Literal l) {
- IRI datatype = l.getDatatype();
- return Literals.isLanguageLiteral(l) || datatype.equals(XSD.STRING);
+ return l.getCoreDatatype() == CoreDatatype.XSD.STRING || Literals.isLanguageLiteral(l);
}
- private static boolean isSupportedDatatype(IRI datatype) {
- return (XSD.STRING.equals(datatype) || XMLDatatypeUtil.isNumericDatatype(datatype)
- || XMLDatatypeUtil.isCalendarDatatype(datatype));
+ private static boolean isSupportedDatatype(CoreDatatype.XSD datatype) {
+ return datatype != null && (datatype == CoreDatatype.XSD.STRING ||
+ datatype.isNumericDatatype() ||
+ datatype.isCalendarDatatype());
}
}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtility.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtility.java
new file mode 100644
index 00000000000..81ca2f95a20
--- /dev/null
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtility.java
@@ -0,0 +1,547 @@
+/*******************************************************************************
+ * Copyright (c) 2022 Eclipse RDF4J contributors.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Distribution License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ ******************************************************************************/
+package org.eclipse.rdf4j.query.algebra.evaluation.util;
+
+import java.util.Objects;
+
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.Duration;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.eclipse.rdf4j.common.annotation.InternalUseOnly;
+import org.eclipse.rdf4j.model.Literal;
+import org.eclipse.rdf4j.model.Value;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
+import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
+import org.eclipse.rdf4j.model.util.Literals;
+import org.eclipse.rdf4j.query.algebra.Compare.CompareOp;
+
+/**
+ * This class will take over for QueryEvaluationUtil. Currently marked as InternalUseOnly because there may still be
+ * changes to how this class works.
+ *
+ * @author Arjohn Kampman
+ * @author Håvard M. Ottestad
+ */
+@InternalUseOnly()
+public class QueryEvaluationUtility {
+
+ /**
+ * Determines the effective boolean value (EBV) of the supplied value as defined in the
+ * SPARQL specification:
+ *
+ * - The EBV of any literal whose type is CoreDatatype.XSD:boolean or numeric is false if the lexical form is not
+ * valid for that datatype (e.g. "abc"^^xsd:integer).
+ *
- If the argument is a typed literal with a datatype of CoreDatatype.XSD:boolean, the EBV is the value of that
+ * argument.
+ *
- If the argument is a plain literal or a typed literal with a datatype of CoreDatatype.XSD:string, the EBV is
+ * false if the operand value has zero length; otherwise the EBV is true.
+ *
- If the argument is a numeric type or a typed literal with a datatype derived from a numeric type, the EBV is
+ * false if the operand value is NaN or is numerically equal to zero; otherwise the EBV is true.
+ *
- All other arguments, including unbound arguments, produce a type error.
+ *
+ *
+ * @param value Some value.
+ * @return The EBV of value.
+ */
+ public static Result getEffectiveBooleanValue(Value value) {
+ if (value.isLiteral()) {
+ Literal literal = (Literal) value;
+ String label = literal.getLabel();
+ CoreDatatype.XSD datatype = literal.getCoreDatatype().asXSDDatatype().orElse(null);
+
+ if (datatype == CoreDatatype.XSD.STRING) {
+ return Result.fromBoolean(label.length() > 0);
+ } else if (datatype == CoreDatatype.XSD.BOOLEAN) {
+ // also false for illegal values
+ return Result.fromBoolean("true".equals(label) || "1".equals(label));
+ } else if (datatype == CoreDatatype.XSD.DECIMAL) {
+ try {
+ String normDec = XMLDatatypeUtil.normalizeDecimal(label);
+ return Result.fromBoolean(!normDec.equals("0.0"));
+ } catch (IllegalArgumentException e) {
+ return Result.fromBoolean(false);
+ }
+ } else if (datatype != null && datatype.isIntegerDatatype()) {
+ try {
+ String normInt = XMLDatatypeUtil.normalize(label, datatype);
+ return Result.fromBoolean(!normInt.equals("0"));
+ } catch (IllegalArgumentException e) {
+ return Result.fromBoolean(false);
+ }
+ } else if (datatype != null && datatype.isFloatingPointDatatype()) {
+ try {
+ String normFP = XMLDatatypeUtil.normalize(label, datatype);
+ return Result.fromBoolean(!normFP.equals("0.0E0") && !normFP.equals("NaN"));
+ } catch (IllegalArgumentException e) {
+ return Result.fromBoolean(false);
+ }
+ }
+
+ }
+
+ return Result.incompatibleValueExpression;
+ }
+
+ public static Result compare(Value leftVal, Value rightVal, CompareOp operator) {
+ return compare(leftVal, rightVal, operator, true);
+ }
+
+ public static Result compare(Value leftVal, Value rightVal, CompareOp operator, boolean strict) {
+ if (leftVal.isLiteral() && rightVal.isLiteral()) {
+ // Both left and right argument is a Literal
+ return compareLiterals((Literal) leftVal, (Literal) rightVal, operator, strict);
+ } else {
+ // All other value combinations
+ switch (operator) {
+ case EQ:
+ return Result.fromBoolean(Objects.equals(leftVal, rightVal));
+ case NE:
+ return Result.fromBoolean(!Objects.equals(leftVal, rightVal));
+ default:
+ return Result.incompatibleValueExpression;
+ }
+ }
+ }
+
+ /**
+ * Compares the supplied {@link Literal} arguments using the supplied operator, using strict (minimally-conforming)
+ * SPARQL 1.1 operator behavior.
+ *
+ * @param leftLit the left literal argument of the comparison.
+ * @param rightLit the right literal argument of the comparison.
+ * @param operator the comparison operator to use.
+ * @return {@code true} if execution of the supplied operator on the supplied arguments succeeds, {@code false}
+ * otherwise.
+ */
+ public static Result compareLiterals(Literal leftLit, Literal rightLit, CompareOp operator) {
+ return compareLiterals(leftLit, rightLit, operator, true);
+ }
+
+ public static Order compareLiterals(Literal leftLit, Literal rightLit, boolean strict) {
+ // type precendence:
+ // - simple literal
+ // - numeric
+ // - CoreDatatype.XSD:boolean
+ // - CoreDatatype.XSD:dateTime
+ // - CoreDatatype.XSD:string
+ // - RDF term (equal and unequal only)
+
+ CoreDatatype leftCoreDatatype = leftLit.getCoreDatatype();
+ CoreDatatype rightCoreDatatype = rightLit.getCoreDatatype();
+
+ boolean leftLangLit = leftCoreDatatype == CoreDatatype.RDF.LANGSTRING;
+ boolean rightLangLit = rightCoreDatatype == CoreDatatype.RDF.LANGSTRING;
+
+ CoreDatatype.XSD leftXSDDatatype = leftCoreDatatype.asXSDDatatype().orElse(null);
+ CoreDatatype.XSD rightXSDDatatype = rightCoreDatatype.asXSDDatatype().orElse(null);
+
+ // for purposes of query evaluation in SPARQL, simple literals and string-typed literals with the same lexical
+ // value are considered equal.
+
+ if (leftCoreDatatype == CoreDatatype.XSD.STRING && rightCoreDatatype == CoreDatatype.XSD.STRING) {
+ return Order.from(leftLit.getLabel().compareTo(rightLit.getLabel()));
+ } else if (!(leftLangLit || rightLangLit)) {
+
+ CoreDatatype.XSD commonDatatype = getCommonDatatype(strict, leftXSDDatatype, rightXSDDatatype);
+
+ if (commonDatatype != null) {
+
+ try {
+ Order order = handleCommonDatatype(leftLit, rightLit, strict, leftXSDDatatype, rightXSDDatatype,
+ leftLangLit, rightLangLit, commonDatatype);
+
+ if (order == Order.illegalArgument) {
+ if (leftLit.equals(rightLit)) {
+ return Order.equal;
+ }
+ }
+
+ if (order != null) {
+ return order;
+ }
+ } catch (IllegalArgumentException e) {
+ if (leftLit.equals(rightLit)) {
+ return Order.equal;
+ }
+ }
+
+ }
+ }
+
+ // All other cases, e.g. literals with languages, unequal or
+ // unordered datatypes, etc. These arguments can only be compared
+ // using the operators 'EQ' and 'NE'. See SPARQL's RDFterm-equal
+ // operator
+
+ return otherCases(leftLit, rightLit, leftXSDDatatype, rightXSDDatatype, leftLangLit, rightLangLit);
+
+ }
+
+ /**
+ * Compares the supplied {@link Literal} arguments using the supplied operator.
+ *
+ * @param leftLit the left literal argument of the comparison.
+ * @param rightLit the right literal argument of the comparison.
+ * @param operator the comparison operator to use.
+ * @param strict boolean indicating whether comparison should use strict (minimally-conforming) SPARQL 1.1
+ * operator behavior, or extended behavior.
+ * @return {@code true} if execution of the supplied operator on the supplied arguments succeeds, {@code false}
+ * otherwise.
+ */
+ public static Result compareLiterals(Literal leftLit, Literal rightLit, CompareOp operator, boolean strict) {
+ Order order = compareLiterals(leftLit, rightLit, strict);
+ return order.toResult(operator);
+ }
+
+ private static Order handleCommonDatatype(Literal leftLit, Literal rightLit, boolean strict,
+ CoreDatatype.XSD leftCoreDatatype, CoreDatatype.XSD rightCoreDatatype, boolean leftLangLit,
+ boolean rightLangLit, CoreDatatype.XSD commonDatatype) {
+ if (commonDatatype == CoreDatatype.XSD.DOUBLE) {
+ return Order.from(Double.compare(leftLit.doubleValue(), rightLit.doubleValue()));
+ } else if (commonDatatype == CoreDatatype.XSD.FLOAT) {
+ return Order.from(Float.compare(leftLit.floatValue(), rightLit.floatValue()));
+ } else if (commonDatatype == CoreDatatype.XSD.DECIMAL) {
+ return Order.from(leftLit.decimalValue().compareTo(rightLit.decimalValue()));
+ } else if (commonDatatype.isIntegerDatatype()) {
+ return Order.from(leftLit.integerValue().compareTo(rightLit.integerValue()));
+ } else if (commonDatatype == CoreDatatype.XSD.BOOLEAN) {
+ return Order.from(Boolean.compare(leftLit.booleanValue(), rightLit.booleanValue()));
+ } else if (commonDatatype.isCalendarDatatype()) {
+ XMLGregorianCalendar left = leftLit.calendarValue();
+ XMLGregorianCalendar right = rightLit.calendarValue();
+
+ int compare = left.compare(right);
+
+ // Note: XMLGregorianCalendar.compare() returns compatible values (-1, 0, 1) but INDETERMINATE
+ // needs special treatment
+ if (compare == DatatypeConstants.INDETERMINATE) {
+ // If we compare two CoreDatatype.XSD:dateTime we should use the specific comparison specified in SPARQL
+ // 1.1
+ if (leftCoreDatatype == CoreDatatype.XSD.DATETIME && rightCoreDatatype == CoreDatatype.XSD.DATETIME) {
+ return Order.incompatibleValueExpression;
+ }
+ } else {
+ return Order.from(compare);
+ }
+
+ } else if (!strict && commonDatatype.isDurationDatatype()) {
+ Duration left = XMLDatatypeUtil.parseDuration(leftLit.getLabel());
+ Duration right = XMLDatatypeUtil.parseDuration(rightLit.getLabel());
+ int compare = left.compare(right);
+ if (compare != DatatypeConstants.INDETERMINATE) {
+ return Order.from(compare);
+ } else {
+ return otherCases(leftLit, rightLit, leftCoreDatatype, rightCoreDatatype, leftLangLit, rightLangLit);
+ }
+
+ } else if (commonDatatype == CoreDatatype.XSD.STRING) {
+ return Order.from(leftLit.getLabel().compareTo(rightLit.getLabel()));
+ }
+
+ return null;
+ }
+
+ private static Order otherCases(Literal leftLit, Literal rightLit, CoreDatatype.XSD leftCoreDatatype,
+ CoreDatatype.XSD rightCoreDatatype, boolean leftLangLit, boolean rightLangLit) {
+ boolean literalsEqual = leftLit.equals(rightLit);
+
+ if (!literalsEqual) {
+ if (!leftLangLit && !rightLangLit && isSupportedDatatype(leftCoreDatatype)
+ && isSupportedDatatype(rightCoreDatatype)) {
+ // left and right arguments have incompatible but supported datatypes
+
+ // we need to check that the lexical-to-value mapping for both datatypes succeeds
+ if (!XMLDatatypeUtil.isValidValue(leftLit.getLabel(), leftCoreDatatype)) {
+ return Order.incompatibleValueExpression;
+ }
+
+ if (!XMLDatatypeUtil.isValidValue(rightLit.getLabel(), rightCoreDatatype)) {
+ return Order.incompatibleValueExpression;
+ }
+
+ boolean leftString = leftCoreDatatype == CoreDatatype.XSD.STRING;
+ boolean leftNumeric = leftCoreDatatype.isNumericDatatype();
+ boolean leftDate = leftCoreDatatype.isCalendarDatatype();
+
+ boolean rightString = rightCoreDatatype == CoreDatatype.XSD.STRING;
+ boolean rightNumeric = rightCoreDatatype.isNumericDatatype();
+ boolean rightDate = rightCoreDatatype.isCalendarDatatype();
+
+ if (leftString != rightString) {
+ return Order.incompatibleValueExpression;
+ }
+ if (leftNumeric != rightNumeric) {
+ return Order.incompatibleValueExpression;
+ }
+ if (leftDate != rightDate) {
+ return Order.incompatibleValueExpression;
+ }
+ } else if (!leftLangLit && !rightLangLit) {
+ // For literals with unsupported datatypes we don't know if their values are equal
+ return Order.incompatibleValueExpression;
+ }
+ }
+
+ if (literalsEqual) {
+ return Order.equal;
+ }
+ return Order.notEqual;
+ }
+
+ private static CoreDatatype.XSD getCommonDatatype(boolean strict, CoreDatatype.XSD leftCoreDatatype,
+ CoreDatatype.XSD rightCoreDatatype) {
+ if (leftCoreDatatype != null && rightCoreDatatype != null) {
+ if (leftCoreDatatype == rightCoreDatatype) {
+ return leftCoreDatatype;
+ } else if (leftCoreDatatype.isNumericDatatype() && rightCoreDatatype.isNumericDatatype()) {
+ // left and right arguments have different datatypes, try to find a more general, shared datatype
+ if (leftCoreDatatype == CoreDatatype.XSD.DOUBLE || rightCoreDatatype == CoreDatatype.XSD.DOUBLE) {
+ return CoreDatatype.XSD.DOUBLE;
+ } else if (leftCoreDatatype == CoreDatatype.XSD.FLOAT || rightCoreDatatype == CoreDatatype.XSD.FLOAT) {
+ return CoreDatatype.XSD.FLOAT;
+ } else if (leftCoreDatatype == CoreDatatype.XSD.DECIMAL
+ || rightCoreDatatype == CoreDatatype.XSD.DECIMAL) {
+ return CoreDatatype.XSD.DECIMAL;
+ } else {
+ return CoreDatatype.XSD.INTEGER;
+ }
+ } else if (!strict && leftCoreDatatype.isCalendarDatatype() && rightCoreDatatype.isCalendarDatatype()) {
+ // We're not running in strict eval mode so we use extended datatype comparsion.
+ return CoreDatatype.XSD.DATETIME;
+ } else if (!strict && leftCoreDatatype.isDurationDatatype() && rightCoreDatatype.isDurationDatatype()) {
+ return CoreDatatype.XSD.DURATION;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Checks whether the supplied value is a "plain literal". A "plain literal" is a literal with no datatype and
+ * optionally a language tag.
+ *
+ * @see RDF Literal
+ * Documentation
+ */
+ public static boolean isPlainLiteral(Value v) {
+ if (v.isLiteral()) {
+ return isPlainLiteral(((Literal) v));
+ }
+ return false;
+ }
+
+ public static boolean isPlainLiteral(Literal l) {
+ assert l.getLanguage().isEmpty() || (l.getCoreDatatype() == CoreDatatype.RDF.LANGSTRING);
+ return l.getCoreDatatype() == CoreDatatype.XSD.STRING || l.getCoreDatatype() == CoreDatatype.RDF.LANGSTRING;
+ }
+
+ /**
+ * Checks whether the supplied value is a "simple literal". A "simple literal" is a literal with no language tag nor
+ * datatype.
+ *
+ * @see SPARQL Simple Literal Documentation
+ */
+ public static boolean isSimpleLiteral(Value v) {
+ if (v.isLiteral()) {
+ return isSimpleLiteral((Literal) v);
+ }
+
+ return false;
+ }
+
+// public static boolean isPlainLiteral(Literal l) {
+// return l.getCoreDatatype().filter(d -> d == CoreDatatype.XSD.STRING).isPresent();
+//// return l.getCoreDatatype().orElse(null) == CoreDatatype.XSD.STRING;
+// }
+
+ /**
+ * Checks whether the supplied literal is a "simple literal". A "simple literal" is a literal with no language tag
+ * and the datatype {@link CoreDatatype.XSD#STRING}.
+ *
+ * @see SPARQL Simple Literal Documentation
+ */
+ public static boolean isSimpleLiteral(Literal l) {
+ return l.getCoreDatatype() == CoreDatatype.XSD.STRING;
+ }
+
+ /**
+ * Checks whether the supplied literal is a "simple literal". A "simple literal" is a literal with no language tag
+ * and the datatype {@link CoreDatatype.XSD#STRING}.
+ *
+ * @see SPARQL Simple Literal Documentation
+ */
+ public static boolean isSimpleLiteral(boolean isLang, CoreDatatype datatype) {
+ return datatype == CoreDatatype.XSD.STRING;
+ }
+
+ /**
+ * Checks whether the supplied literal is a "string literal". A "string literal" is either a simple literal, a plain
+ * literal with language tag, or a literal with datatype CoreDatatype.XSD:string.
+ *
+ * @see SPARQL Functions on Strings Documentation
+ */
+ public static boolean isStringLiteral(Value v) {
+ if (v.isLiteral()) {
+ return isStringLiteral((Literal) v);
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks whether the supplied two literal arguments are 'argument compatible' according to the SPARQL definition.
+ *
+ * @param arg1 the first argument
+ * @param arg2 the second argument
+ * @return true iff the two supplied arguments are argument compatible, false otherwise
+ * @see SPARQL Argument Compatibility
+ * Rules
+ */
+ public static boolean compatibleArguments(Literal arg1, Literal arg2) {
+ // 1. The arguments are literals typed as CoreDatatype.XSD:string
+ // 2. The arguments are language literals with identical language tags
+ // 3. The first argument is a language literal and the second
+ // argument is a literal typed as CoreDatatype.XSD:string
+
+ return (isSimpleLiteral(arg1) && isSimpleLiteral(arg2))
+ || (Literals.isLanguageLiteral(arg1) && Literals.isLanguageLiteral(arg2)
+ && arg1.getLanguage().equals(arg2.getLanguage()))
+ || (Literals.isLanguageLiteral(arg1) && isSimpleLiteral(arg2));
+ }
+
+ /**
+ * Checks whether the supplied literal is a "string literal". A "string literal" is either a simple literal, a plain
+ * literal with language tag, or a literal with datatype CoreDatatype.XSD:string.
+ *
+ * @see SPARQL Functions on Strings Documentation
+ */
+ public static boolean isStringLiteral(Literal l) {
+ return l.getCoreDatatype() == CoreDatatype.XSD.STRING || l.getCoreDatatype() == CoreDatatype.RDF.LANGSTRING;
+ }
+
+ private static boolean isSupportedDatatype(CoreDatatype.XSD datatype) {
+ return datatype != null && (datatype == CoreDatatype.XSD.STRING || datatype.isNumericDatatype()
+ || datatype.isCalendarDatatype());
+ }
+
+ public enum Result {
+ _true(true),
+ _false(false),
+ incompatibleValueExpression(),
+ illegalArgument();
+
+ static Result fromBoolean(boolean b) {
+ if (b) {
+ return _true;
+ }
+ return _false;
+ }
+
+ private final boolean value;
+ private final boolean isIncompatible;
+
+ Result(boolean value) {
+ this.value = value;
+ isIncompatible = false;
+ }
+
+ Result() {
+ isIncompatible = true;
+ value = false;
+ }
+
+ public boolean orElse(boolean alternative) {
+ if (this == incompatibleValueExpression) {
+ return alternative;
+ } else if (this == illegalArgument) {
+ throw new IllegalStateException("IllegalArgument needs to be handled");
+ }
+ return value;
+ }
+ }
+
+ enum Order {
+ smaller(-1),
+ greater(1),
+ equal(0),
+ notEqual(0),
+ incompatibleValueExpression(0),
+ illegalArgument(0);
+
+ private final int value;
+
+ Order(int value) {
+ this.value = value;
+ }
+
+ public static Order from(int value) {
+ if (value < 0) {
+ return smaller;
+ }
+ if (value > 0) {
+ return greater;
+ }
+ return equal;
+ }
+
+ public int asInt() {
+ if (!isValid() && this != notEqual) {
+ throw new IllegalStateException();
+ }
+ return value;
+ }
+
+ public boolean isValid() {
+ return !(this == incompatibleValueExpression || this == illegalArgument);
+ }
+
+ public Result toResult(CompareOp operator) {
+ if (!isValid()) {
+ if (this == incompatibleValueExpression) {
+ return Result.incompatibleValueExpression;
+ }
+ if (this == illegalArgument) {
+ return Result.illegalArgument;
+ }
+ }
+
+ if (this == notEqual) {
+ switch (operator) {
+ case EQ:
+ return Result._false;
+ case NE:
+ return Result._true;
+ case LT:
+ case LE:
+ case GE:
+ case GT:
+ return Result.incompatibleValueExpression;
+ default:
+ return Result.illegalArgument;
+ }
+ }
+
+ switch (operator) {
+ case LT:
+ return Result.fromBoolean(value < 0);
+ case LE:
+ return Result.fromBoolean(value <= 0);
+ case EQ:
+ return Result.fromBoolean(value == 0);
+ case NE:
+ return Result.fromBoolean(value != 0);
+ case GE:
+ return Result.fromBoolean(value >= 0);
+ case GT:
+ return Result.fromBoolean(value > 0);
+ default:
+ return Result.illegalArgument;
+ }
+ }
+ }
+}
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparator.java
index 33fd5a1909f..a0eceffb8ff 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparator.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparator.java
@@ -15,11 +15,7 @@
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Triple;
import org.eclipse.rdf4j.model.Value;
-import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
-import org.eclipse.rdf4j.model.util.Literals;
-import org.eclipse.rdf4j.model.vocabulary.XSD;
-import org.eclipse.rdf4j.query.algebra.Compare.CompareOp;
-import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
/**
* A comparator that compares values according the SPARQL value ordering as specified in
@@ -108,27 +104,34 @@ private int compareURIs(IRI leftURI, IRI rightURI) {
private int compareLiterals(Literal leftLit, Literal rightLit) {
// Additional constraint for ORDER BY: "A plain literal is lower
- // than an RDF literal with type xsd:string of the same lexical
+ // than an RDF literal with type CoreDatatype.XSD:string of the same lexical
// form."
- if (!(QueryEvaluationUtil.isPlainLiteral(leftLit) || QueryEvaluationUtil.isPlainLiteral(rightLit))) {
- try {
- boolean isSmaller = QueryEvaluationUtil.compareLiterals(leftLit, rightLit, CompareOp.LT, strict);
- if (isSmaller) {
- return -1;
- } else {
- boolean isEquivalent = QueryEvaluationUtil.compareLiterals(leftLit, rightLit, CompareOp.EQ, strict);
- if (isEquivalent) {
- return 0;
- }
- return 1;
- }
- } catch (ValueExprEvaluationException e) {
- // literals cannot be compared using the '<' operator, continue
- // below
+ if (!(QueryEvaluationUtility.isPlainLiteral(leftLit) || QueryEvaluationUtility.isPlainLiteral(rightLit))) {
+ QueryEvaluationUtility.Order order = compareNonPlainLiterals(leftLit, rightLit);
+ if (order.isValid()) {
+ return order.asInt();
+ }
+ if (order == QueryEvaluationUtility.Order.illegalArgument) {
+ throw new IllegalStateException();
}
}
+ return comparePlainLiterals(leftLit, rightLit);
+ }
+
+ private QueryEvaluationUtility.Order compareNonPlainLiterals(Literal leftLit, Literal rightLit) {
+
+ QueryEvaluationUtility.Order order = QueryEvaluationUtility.compareLiterals(leftLit, rightLit, strict);
+
+ if (order == QueryEvaluationUtility.Order.notEqual) {
+ return QueryEvaluationUtility.Order.smaller;
+ }
+
+ return order;
+ }
+
+ private int comparePlainLiterals(Literal leftLit, Literal rightLit) {
int result = 0;
// FIXME: Confirm these rules work with RDF-1.1
@@ -139,101 +142,74 @@ private int compareLiterals(Literal leftLit, Literal rightLit) {
if (leftDatatype != null) {
if (rightDatatype != null) {
// Both literals have datatypes
- Optional leftXmlDatatype = Literals.getXsdDatatype(leftLit);
- Optional rightXmlDatatype = Literals.getXsdDatatype(rightLit);
+ CoreDatatype.XSD leftXmlDatatype = leftLit.getCoreDatatype().asXSDDatatype().orElse(null);
+ CoreDatatype.XSD rightXmlDatatype = rightLit.getCoreDatatype().asXSDDatatype().orElse(null);
- if (leftXmlDatatype.isPresent() && rightXmlDatatype.isPresent()) {
- result = compareDatatypes(leftXmlDatatype.get(), rightXmlDatatype.get());
- } else {
- result = compareDatatypes(leftDatatype, rightDatatype);
+ result = compareDatatypes(leftXmlDatatype, rightXmlDatatype, leftDatatype, rightDatatype);
+ if (result != 0) {
+ return result;
}
} else {
- result = 1;
+ return 1;
}
} else if (rightDatatype != null) {
- result = -1;
+ return -1;
}
- if (result == 0) {
- // datatypes are equal or both literals are untyped; sort by language
- // tags, simple literals come before literals with language tags
- Optional leftLanguage = leftLit.getLanguage();
- Optional rightLanguage = rightLit.getLanguage();
+ // datatypes are equal or both literals are untyped; sort by language
+ // tags, simple literals come before literals with language tags
+ Optional leftLanguage = leftLit.getLanguage();
+ Optional rightLanguage = rightLit.getLanguage();
- if (leftLanguage.isPresent()) {
- if (rightLanguage.isPresent()) {
- result = leftLanguage.get().compareTo(rightLanguage.get());
- } else {
- result = 1;
+ if (leftLanguage.isPresent()) {
+ if (rightLanguage.isPresent()) {
+ result = leftLanguage.get().compareTo(rightLanguage.get());
+ if (result != 0) {
+ return result;
}
- } else if (rightLanguage.isPresent()) {
- result = -1;
+ } else {
+ return 1;
}
+ } else if (rightLanguage.isPresent()) {
+ return -1;
}
- if (result == 0) {
- // Literals are equal as fas as their datatypes and language tags are
- // concerned, compare their labels
- result = leftLit.getLabel().compareTo(rightLit.getLabel());
- }
-
- return result;
+ // Literals are equal as fas as their datatypes and language tags are
+ // concerned, compare their labels
+ return leftLit.getLabel().compareTo(rightLit.getLabel());
}
- /**
- * Compares two literal datatypes and indicates if one should be ordered after the other. This algorithm ensures
- * that compatible ordered datatypes (numeric and date/time) are grouped together so that
- * {@link QueryEvaluationUtil#compareLiterals(Literal, Literal, CompareOp)} is used in consecutive ordering steps.
- */
- private int compareDatatypes(IRI leftDatatype, IRI rightDatatype) {
- if (XMLDatatypeUtil.isNumericDatatype(leftDatatype)) {
- if (XMLDatatypeUtil.isNumericDatatype(rightDatatype)) {
+ private int compareDatatypes(CoreDatatype.XSD leftDatatype, CoreDatatype.XSD rightDatatype, IRI leftDatatypeIRI,
+ IRI rightDatatypeIRI) {
+ if (leftDatatype != null && leftDatatype == rightDatatype) {
+ return 0;
+ } else if (leftDatatype != null && leftDatatype.isNumericDatatype()) {
+ if (rightDatatype != null && rightDatatype.isNumericDatatype()) {
// both are numeric datatypes
- return compareURIs(leftDatatype, rightDatatype);
+ return leftDatatype.compareTo(rightDatatype);
} else {
return -1;
}
- } else if (XMLDatatypeUtil.isNumericDatatype(rightDatatype)) {
+ } else if (rightDatatype != null && rightDatatype.isNumericDatatype()) {
return 1;
- } else if (XMLDatatypeUtil.isCalendarDatatype(leftDatatype)) {
- if (XMLDatatypeUtil.isCalendarDatatype(rightDatatype)) {
- // both are calendar datatypes
- return compareURIs(leftDatatype, rightDatatype);
+ } else if (leftDatatype != null && leftDatatype.isCalendarDatatype()) {
+ if (rightDatatype != null && rightDatatype.isCalendarDatatype()) {
+ return leftDatatype.compareTo(rightDatatype);
} else {
return -1;
}
- } else if (XMLDatatypeUtil.isCalendarDatatype(rightDatatype)) {
+ } else if (rightDatatype != null && rightDatatype.isCalendarDatatype()) {
return 1;
- } else {
- // incompatible or unordered datatypes
- return compareURIs(leftDatatype, rightDatatype);
}
- }
- private int compareDatatypes(XSD.Datatype leftDatatype, XSD.Datatype rightDatatype) {
- if (leftDatatype.isNumericDatatype()) {
- if (rightDatatype.isNumericDatatype()) {
- // both are numeric datatypes
- return compareURIs(leftDatatype.getIri(), rightDatatype.getIri());
- } else {
- return -1;
- }
- } else if (rightDatatype.isNumericDatatype()) {
- return 1;
- } else if (leftDatatype.isCalendarDatatype()) {
- if (rightDatatype.isCalendarDatatype()) {
- // both are calendar datatype
- return compareURIs(leftDatatype.getIri(), rightDatatype.getIri());
- } else {
- return -1;
- }
- } else if (rightDatatype.isCalendarDatatype()) {
- return 1;
- } else {
- // incompatible or unordered datatype
- return compareURIs(leftDatatype.getIri(), rightDatatype.getIri());
+ if (leftDatatype != null && rightDatatype != null) {
+ return leftDatatype.compareTo(rightDatatype);
}
+
+ // incompatible or unordered datatype
+ return compareURIs(leftDatatypeIRI, rightDatatypeIRI);
+
}
private int compareTriples(Triple leftTriple, Triple rightTriple) {
diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/XMLDatatypeMathUtil.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/XMLDatatypeMathUtil.java
index c9cf8982600..0b4a5731df2 100644
--- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/XMLDatatypeMathUtil.java
+++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/XMLDatatypeMathUtil.java
@@ -11,11 +11,10 @@
import javax.xml.datatype.Duration;
import javax.xml.datatype.XMLGregorianCalendar;
-import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
-import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.query.algebra.MathExpr.MathOp;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
@@ -36,29 +35,27 @@ public class XMLDatatypeMathUtil {
* @return a datatype literal
*/
public static Literal compute(Literal leftLit, Literal rightLit, MathOp op) throws ValueExprEvaluationException {
- IRI leftDatatype = leftLit.getDatatype();
- IRI rightDatatype = rightLit.getDatatype();
-
- if (XMLDatatypeUtil.isNumericDatatype(leftDatatype) && XMLDatatypeUtil.isNumericDatatype(rightDatatype)) {
- return MathUtil.compute(leftLit, rightLit, op);
- } else if (XMLDatatypeUtil.isDurationDatatype(leftDatatype)
- && XMLDatatypeUtil.isDurationDatatype(rightDatatype)) {
- return operationsBetweenDurations(leftLit, rightLit, op);
- } else if (XMLDatatypeUtil.isDecimalDatatype(leftDatatype)
- && XMLDatatypeUtil.isDurationDatatype(rightDatatype)) {
- return operationsBetweenDurationAndDecimal(rightLit, leftLit, op);
- } else if (XMLDatatypeUtil.isDurationDatatype(leftDatatype)
- && XMLDatatypeUtil.isDecimalDatatype(rightDatatype)) {
- return operationsBetweenDurationAndDecimal(leftLit, rightLit, op);
- } else if (XMLDatatypeUtil.isCalendarDatatype(leftDatatype)
- && XMLDatatypeUtil.isDurationDatatype(rightDatatype)) {
- return operationsBetweenCalendarAndDuration(leftLit, rightLit, op);
- } else if (XMLDatatypeUtil.isDurationDatatype(leftDatatype)
- && XMLDatatypeUtil.isCalendarDatatype(rightDatatype)) {
- return operationsBetweenDurationAndCalendar(leftLit, rightLit, op);
- } else {
- throw new ValueExprEvaluationException("Mathematical operators are not supported on these operands");
+ CoreDatatype.XSD leftDatatype = leftLit.getCoreDatatype().asXSDDatatype().orElse(null);
+ CoreDatatype.XSD rightDatatype = rightLit.getCoreDatatype().asXSDDatatype().orElse(null);
+
+ if (leftDatatype != null && rightDatatype != null) {
+ if (leftDatatype.isNumericDatatype() && rightDatatype.isNumericDatatype()) {
+ return MathUtil.compute(leftLit, rightLit, op);
+ } else if (leftDatatype.isDurationDatatype() && rightDatatype.isDurationDatatype()) {
+ return operationsBetweenDurations(leftLit, rightLit, op);
+ } else if (leftDatatype.isDecimalDatatype() && rightDatatype.isDurationDatatype()) {
+ return operationsBetweenDurationAndDecimal(rightLit, leftLit, op);
+ } else if (leftDatatype.isDurationDatatype() && rightDatatype.isDecimalDatatype()) {
+ return operationsBetweenDurationAndDecimal(leftLit, rightLit, op);
+ } else if (leftDatatype.isCalendarDatatype() && rightDatatype.isDurationDatatype()) {
+ return operationsBetweenCalendarAndDuration(leftLit, rightLit, op);
+ } else if (leftDatatype.isDurationDatatype() && rightDatatype.isCalendarDatatype()) {
+ return operationsBetweenDurationAndCalendar(leftLit, rightLit, op);
+ }
}
+
+ throw new ValueExprEvaluationException("Mathematical operators are not supported on these operands");
+
}
private static Literal operationsBetweenDurations(Literal leftLit, Literal rightLit, MathOp op) {
@@ -156,7 +153,7 @@ private static Literal buildLiteral(Duration duration) {
return SimpleValueFactory.getInstance().createLiteral(duration.toString(), getDatatypeForDuration(duration));
}
- private static IRI getDatatypeForDuration(Duration duration) {
+ private static CoreDatatype.XSD getDatatypeForDuration(Duration duration) {
// Could not be implemented with Duration.getXMLSchemaType that is too strict ("P1Y" is considered invalid)
boolean yearSet = duration.isSet(DatatypeConstants.YEARS);
@@ -167,11 +164,11 @@ private static IRI getDatatypeForDuration(Duration duration) {
boolean secondSet = duration.isSet(DatatypeConstants.SECONDS);
if (!yearSet && !monthSet) {
- return XSD.DAYTIMEDURATION;
+ return CoreDatatype.XSD.DAYTIMEDURATION;
}
if (!daySet && !hourSet && !minuteSet && !secondSet) {
- return XSD.YEARMONTHDURATION;
+ return CoreDatatype.XSD.YEARMONTHDURATION;
}
- return XSD.DURATION;
+ return CoreDatatype.XSD.DURATION;
}
}
diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/BindingSetAssignmentInlinerTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/BindingSetAssignmentInlinerTest.java
index 727b8a0f7ca..978ef7500c9 100644
--- a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/BindingSetAssignmentInlinerTest.java
+++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/BindingSetAssignmentInlinerTest.java
@@ -1,9 +1,9 @@
-/*******************************************************************************
- * Copyright (c) 2021 Eclipse RDF4J contributors.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Distribution License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
+/*******************************************************************************
+ * Copyright (c) 2021 Eclipse RDF4J contributors.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Distribution License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
*******************************************************************************/
package org.eclipse.rdf4j.query.algebra.evaluation.impl;
diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ParentReferenceCleanerTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ParentReferenceCleanerTest.java
index 9a8ed968640..af59c45f0b9 100644
--- a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ParentReferenceCleanerTest.java
+++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ParentReferenceCleanerTest.java
@@ -1,9 +1,9 @@
-/*******************************************************************************
- * Copyright (c) 2021 Eclipse RDF4J contributors.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Distribution License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
+/*******************************************************************************
+ * Copyright (c) 2021 Eclipse RDF4J contributors.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Distribution License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
*******************************************************************************/
package org.eclipse.rdf4j.query.algebra.evaluation.impl;
diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtilityTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtilityTest.java
new file mode 100644
index 00000000000..25291978fa8
--- /dev/null
+++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtilityTest.java
@@ -0,0 +1,641 @@
+/*******************************************************************************
+ * Copyright (c) 2022 Eclipse RDF4J contributors.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Distribution License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ ******************************************************************************/
+
+package org.eclipse.rdf4j.query.algebra.evaluation.util;
+
+import static org.eclipse.rdf4j.query.algebra.Compare.CompareOp.EQ;
+import static org.eclipse.rdf4j.query.algebra.Compare.CompareOp.LT;
+import static org.eclipse.rdf4j.query.algebra.Compare.CompareOp.NE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Optional;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.eclipse.rdf4j.model.IRI;
+import org.eclipse.rdf4j.model.Literal;
+import org.eclipse.rdf4j.model.ValueFactory;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
+import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
+import org.eclipse.rdf4j.model.vocabulary.XSD;
+import org.eclipse.rdf4j.query.algebra.Compare.CompareOp;
+import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Jeen Broekstra
+ * @author Håvard M. Ottestad
+ */
+public class QueryEvaluationUtilityTest {
+
+ private final ValueFactory f = SimpleValueFactory.getInstance();
+
+ private Literal arg1simple;
+
+ private Literal arg2simple;
+
+ private Literal arg1en;
+
+ private Literal arg2en;
+
+ private Literal arg1cy;
+
+ private Literal arg2cy;
+
+ private Literal arg1string;
+
+ private Literal arg2string;
+
+ private Literal arg1int;
+
+ private Literal arg2int;
+
+ private Literal arg1year;
+
+ private Literal arg2year;
+
+ private Literal arg1dateTime;
+
+ private Literal arg2dateTime;
+
+ private Literal arg1duration;
+
+ private Literal arg2duration;
+
+ private Literal arg1yearMonthDuration;
+
+ private Literal arg2yearMonthDuration;
+
+ private Literal arg1unknown;
+
+ private Literal arg2unknown;
+
+ @Before
+ public void setUp() {
+ arg1simple = f.createLiteral("abc");
+ arg2simple = f.createLiteral("b");
+
+ arg1en = f.createLiteral("abc", "en");
+ arg2en = f.createLiteral("b", "en");
+
+ arg1cy = f.createLiteral("abc", "cy");
+ arg2cy = f.createLiteral("b", "cy");
+
+ arg1string = f.createLiteral("abc", XSD.STRING);
+ arg2string = f.createLiteral("b", XSD.STRING);
+
+ arg1year = f.createLiteral("2007", XSD.GYEAR);
+ arg2year = f.createLiteral("2009", XSD.GYEAR);
+
+ arg1dateTime = f.createLiteral("2009-01-01T20:20:20Z", XSD.DATETIME);
+ arg2dateTime = f.createLiteral("2007-01-01T20:20:20+02:00", XSD.DATETIME);
+
+ arg1int = f.createLiteral(10);
+ arg2int = f.createLiteral(1);
+
+ arg1duration = f.createLiteral("P1Y30DT1H1M1S", XSD.DURATION);
+ arg2duration = f.createLiteral("P1Y31DT1H1M1S", XSD.DURATION);
+
+ arg1yearMonthDuration = f.createLiteral("P1M", XSD.YEARMONTHDURATION);
+ arg2yearMonthDuration = f.createLiteral("P1Y1M", XSD.YEARMONTHDURATION);
+
+ arg1unknown = f.createLiteral("foo", f.createIRI("http://example.com/datatype"));
+ arg2unknown = f.createLiteral("bar", f.createIRI("http://example.com/datatype"));
+ }
+
+ @Test
+ public void testCompatibleArguments() {
+
+ assertTrue(QueryEvaluationUtility.compatibleArguments(arg1simple, arg2simple));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1simple, arg2en));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1simple, arg2cy));
+ assertTrue(QueryEvaluationUtility.compatibleArguments(arg1simple, arg2string));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1simple, arg2int));
+
+ assertTrue(QueryEvaluationUtility.compatibleArguments(arg1en, arg2simple));
+ assertTrue(QueryEvaluationUtility.compatibleArguments(arg1en, arg2en));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg2en, arg2cy));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1en, arg2cy));
+ assertTrue(QueryEvaluationUtility.compatibleArguments(arg1en, arg2string));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1en, arg2int));
+
+ assertTrue(QueryEvaluationUtility.compatibleArguments(arg1cy, arg2simple));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1cy, arg2en));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg2cy, arg2en));
+ assertTrue(QueryEvaluationUtility.compatibleArguments(arg1cy, arg2cy));
+ assertTrue(QueryEvaluationUtility.compatibleArguments(arg1cy, arg2string));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1cy, arg2int));
+
+ assertTrue(QueryEvaluationUtility.compatibleArguments(arg1string, arg2simple));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1string, arg2en));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1string, arg2cy));
+ assertTrue(QueryEvaluationUtility.compatibleArguments(arg1string, arg2string));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1string, arg2int));
+
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1int, arg2simple));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1int, arg2en));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1int, arg2cy));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1int, arg2string));
+ assertFalse(QueryEvaluationUtility.compatibleArguments(arg1int, arg2int));
+
+ }
+
+ @Test
+ public void testCompareEQ() {
+ assertCompareTrue(arg1simple, arg1simple, EQ);
+ assertCompareTrue(arg1en, arg1en, EQ);
+ assertCompareTrue(arg2cy, arg2cy, EQ);
+ assertCompareTrue(arg1string, arg1string, EQ);
+ assertCompareTrue(arg1int, arg1int, EQ);
+ assertCompareTrue(arg1year, arg1year, EQ);
+ assertCompareTrue(arg1dateTime, arg1dateTime, EQ);
+ assertCompareTrue(arg1duration, arg1duration, EQ);
+ assertCompareTrue(arg1yearMonthDuration, arg1yearMonthDuration, EQ);
+ assertCompareException(arg1unknown, arg2unknown, EQ);
+
+ assertCompareFalse(arg1simple, arg2simple, EQ);
+ assertCompareFalse(arg1simple, arg2en, EQ);
+ assertCompareFalse(arg1simple, arg2cy, EQ);
+ assertCompareFalse(arg1simple, arg2string, EQ);
+ assertCompareException(arg1simple, arg2int, EQ);
+ assertCompareException(arg1simple, arg2year, EQ);
+ assertCompareException(arg1simple, arg2unknown, EQ);
+
+ assertCompareFalse(arg1en, arg2simple, EQ);
+ assertCompareFalse(arg1en, arg2en, EQ);
+ assertCompareFalse(arg2en, arg2cy, EQ);
+ assertCompareFalse(arg1en, arg2cy, EQ);
+ assertCompareFalse(arg1en, arg2string, EQ);
+ assertCompareFalse(arg1en, arg2int, EQ);
+ assertCompareFalse(arg1en, arg2unknown, EQ);
+
+ assertCompareFalse(arg1cy, arg2simple, EQ);
+ assertCompareFalse(arg1cy, arg2en, EQ);
+ assertCompareFalse(arg2cy, arg2en, EQ);
+ assertCompareFalse(arg1cy, arg2cy, EQ);
+ assertCompareFalse(arg1cy, arg2string, EQ);
+ assertCompareFalse(arg1cy, arg2int, EQ);
+ assertCompareFalse(arg1cy, arg2unknown, EQ);
+
+ assertCompareFalse(arg1string, arg2simple, EQ);
+ assertCompareFalse(arg1string, arg2en, EQ);
+ assertCompareFalse(arg1string, arg2cy, EQ);
+ assertCompareFalse(arg1string, arg2string, EQ);
+ assertCompareException(arg1string, arg2int, EQ);
+ assertCompareException(arg1string, arg2year, EQ);
+ assertCompareException(arg1string, arg2unknown, EQ);
+
+ assertCompareException(arg1int, arg2simple, EQ);
+ assertCompareFalse(arg1int, arg2en, EQ);
+ assertCompareFalse(arg1int, arg2cy, EQ);
+ assertCompareException(arg1int, arg2string, EQ);
+ assertCompareFalse(arg1int, arg2int, EQ);
+ assertCompareException(arg1int, arg2year, EQ);
+ assertCompareException(arg1int, arg2unknown, EQ);
+
+ assertCompareException(arg1year, arg2simple, EQ);
+ assertCompareFalse(arg1year, arg2en, EQ);
+ assertCompareException(arg1year, arg2string, EQ);
+ assertCompareException(arg1year, arg2int, EQ);
+ assertCompareFalse(arg1year, arg2year, EQ);
+ assertCompareFalse(arg1year, arg2dateTime, EQ);
+ assertCompareException(arg1year, arg2unknown, EQ);
+
+ assertCompareException(arg1dateTime, arg2simple, EQ);
+ assertCompareFalse(arg1dateTime, arg2en, EQ);
+ assertCompareException(arg1dateTime, arg2string, EQ);
+ assertCompareException(arg1dateTime, arg2int, EQ);
+ assertCompareFalse(arg1dateTime, arg2year, EQ);
+ assertCompareFalse(arg1dateTime, arg2dateTime, EQ);
+ assertCompareException(arg1dateTime, arg2unknown, EQ);
+
+ assertCompareException(arg1duration, arg2simple, EQ);
+ assertCompareFalse(arg1duration, arg2en, EQ);
+ assertCompareException(arg1duration, arg2string, EQ);
+ assertCompareException(arg1duration, arg2int, EQ);
+ assertCompareException(arg1duration, arg2year, EQ);
+ assertCompareException(arg1duration, arg2dateTime, EQ);
+ assertCompareException(arg1duration, arg2duration, EQ);
+ assertCompareFalse(arg1duration, arg2duration, EQ, false);
+ assertCompareException(arg1duration, arg2yearMonthDuration, EQ);
+ assertCompareException(arg1duration, arg2yearMonthDuration, EQ, false);
+ assertCompareException(arg1duration, arg2unknown, EQ);
+ }
+
+ @Test
+ public void testCompareNE() {
+ assertCompareFalse(arg1simple, arg1simple, NE);
+ assertCompareFalse(arg1en, arg1en, NE);
+ assertCompareFalse(arg1cy, arg1cy, NE);
+ assertCompareFalse(arg1string, arg1string, NE);
+ assertCompareFalse(arg1int, arg1int, NE);
+ assertCompareFalse(arg1year, arg1year, NE);
+ assertCompareFalse(arg1dateTime, arg1dateTime, NE);
+ assertCompareException(arg1unknown, arg2unknown, NE);
+
+ assertCompareTrue(arg1simple, arg2simple, NE);
+ assertCompareTrue(arg1simple, arg2en, NE);
+ assertCompareTrue(arg1simple, arg2cy, NE);
+ assertCompareTrue(arg1simple, arg2string, NE);
+ assertCompareException(arg1simple, arg2int, NE);
+ assertCompareException(arg1simple, arg2year, NE);
+ assertCompareException(arg1unknown, arg2unknown, NE);
+
+ assertCompareTrue(arg1en, arg2simple, NE);
+ assertCompareTrue(arg1en, arg2en, NE);
+ assertCompareTrue(arg2en, arg2cy, NE);
+ assertCompareTrue(arg1en, arg2cy, NE);
+ assertCompareTrue(arg1en, arg2string, NE);
+ assertCompareTrue(arg1en, arg2int, NE);
+ assertCompareTrue(arg1en, arg2unknown, NE);
+
+ assertCompareTrue(arg1cy, arg2simple, NE);
+ assertCompareTrue(arg1cy, arg2en, NE);
+ assertCompareTrue(arg2cy, arg2en, NE);
+ assertCompareTrue(arg1cy, arg2cy, NE);
+ assertCompareTrue(arg1cy, arg2string, NE);
+ assertCompareTrue(arg1cy, arg2int, NE);
+ assertCompareTrue(arg1cy, arg2unknown, NE);
+
+ assertCompareTrue(arg1string, arg2simple, NE);
+ assertCompareTrue(arg1string, arg2en, NE);
+ assertCompareTrue(arg1string, arg2cy, NE);
+ assertCompareTrue(arg1string, arg2string, NE);
+ assertCompareException(arg1string, arg2int, NE);
+ assertCompareException(arg1string, arg2year, NE);
+ assertCompareException(arg1string, arg2unknown, NE);
+
+ assertCompareException(arg1int, arg2simple, NE);
+ assertCompareTrue(arg1int, arg2en, NE);
+ assertCompareTrue(arg1int, arg2cy, NE);
+ assertCompareException(arg1int, arg2string, NE);
+ assertCompareTrue(arg1int, arg2int, NE);
+ assertCompareException(arg1int, arg2year, NE);
+ assertCompareException(arg1int, arg2unknown, NE);
+
+ assertCompareException(arg1year, arg2simple, NE);
+ assertCompareTrue(arg1year, arg2en, NE);
+ assertCompareException(arg1year, arg2string, NE);
+ assertCompareException(arg1year, arg2int, NE);
+ assertCompareTrue(arg1year, arg2year, NE);
+ assertCompareTrue(arg1year, arg2dateTime, NE);
+ assertCompareException(arg1year, arg2unknown, NE);
+
+ assertCompareException(arg1dateTime, arg2simple, NE);
+ assertCompareTrue(arg1dateTime, arg2en, NE);
+ assertCompareException(arg1dateTime, arg2string, NE);
+ assertCompareException(arg1dateTime, arg2int, NE);
+ assertCompareTrue(arg1dateTime, arg2year, NE);
+ assertCompareTrue(arg1dateTime, arg2dateTime, NE);
+ assertCompareException(arg1dateTime, arg2unknown, NE);
+
+ assertCompareException(arg1duration, arg2simple, NE);
+ assertCompareTrue(arg1duration, arg2en, NE);
+ assertCompareException(arg1duration, arg2string, NE);
+ assertCompareException(arg1duration, arg2int, NE);
+ assertCompareException(arg1duration, arg2year, NE);
+ assertCompareException(arg1duration, arg2dateTime, NE);
+ assertCompareException(arg1duration, arg2duration, NE);
+ assertCompareTrue(arg1duration, arg2duration, NE, false);
+ assertCompareException(arg1duration, arg2yearMonthDuration, NE);
+ assertCompareException(arg1duration, arg2yearMonthDuration, NE, false);
+ assertCompareException(arg1duration, arg2unknown, NE);
+ }
+
+ @Test
+ public void testCompareLT() {
+ assertCompareFalse(arg1simple, arg1simple, LT);
+
+// The arguments are equal, so they one can not be less than the other.
+// assertCompareException(arg1en, arg1en, LT);
+
+ assertCompareFalse(arg1string, arg1string, LT);
+ assertCompareFalse(arg1int, arg1int, LT);
+ assertCompareFalse(arg1year, arg1year, LT);
+ assertCompareFalse(arg1dateTime, arg1dateTime, LT);
+ assertCompareException(arg1unknown, arg2unknown, LT);
+
+ assertCompareTrue(arg1simple, arg2simple, LT);
+ assertCompareException(arg1simple, arg2en, LT);
+ assertCompareTrue(arg1simple, arg2string, LT);
+ assertCompareException(arg1simple, arg2int, LT);
+ assertCompareException(arg1simple, arg2year, LT);
+ assertCompareException(arg1unknown, arg2unknown, LT);
+
+ assertCompareException(arg1en, arg2simple, LT);
+ assertCompareException(arg1en, arg2en, LT);
+ assertCompareException(arg1en, arg2string, LT);
+ assertCompareException(arg1en, arg2int, LT);
+ assertCompareException(arg1en, arg2unknown, LT);
+
+ assertCompareTrue(arg1string, arg2simple, LT);
+ assertCompareException(arg1string, arg2en, LT);
+ assertCompareTrue(arg1string, arg2string, LT);
+ assertCompareException(arg1string, arg2int, LT);
+ assertCompareException(arg1string, arg2year, LT);
+ assertCompareException(arg1string, arg2unknown, LT);
+
+ assertCompareException(arg1int, arg2simple, LT);
+ assertCompareException(arg1int, arg2en, LT);
+ assertCompareException(arg1int, arg2string, LT);
+ assertCompareFalse(arg1int, arg2int, LT);
+ assertCompareException(arg1int, arg2year, LT);
+ assertCompareException(arg1int, arg2unknown, LT);
+
+ assertCompareException(arg1year, arg2simple, LT);
+ assertCompareException(arg1year, arg2en, LT);
+ assertCompareException(arg1year, arg2string, LT);
+ assertCompareException(arg1year, arg2int, LT);
+ assertCompareTrue(arg1year, arg2year, LT);
+
+ // comparison between xsd:gYear and xsd:dateTime should raise type error in strict mode
+ assertCompareException(arg1year, arg1dateTime, LT);
+
+ // ... but should succeed in extended mode.
+ assertCompareTrue(arg1year, arg1dateTime, LT, false);
+
+ assertCompareException(arg1year, arg2dateTime, LT);
+ assertCompareException(arg1year, arg2unknown, LT);
+
+ assertCompareException(arg1dateTime, arg2simple, LT);
+ assertCompareException(arg1dateTime, arg2en, LT);
+ assertCompareException(arg1dateTime, arg2string, LT);
+ assertCompareException(arg1dateTime, arg2int, LT);
+ assertCompareFalse(arg1dateTime, arg1year, LT, false);
+ assertCompareException(arg1dateTime, arg2year, LT);
+ assertCompareFalse(arg1dateTime, arg2dateTime, LT);
+ assertCompareException(arg1dateTime, arg2unknown, LT);
+
+ assertCompareException(arg1duration, arg2simple, LT);
+ assertCompareException(arg1duration, arg2en, LT);
+ assertCompareException(arg1duration, arg2string, LT);
+ assertCompareException(arg1duration, arg2int, LT);
+ assertCompareException(arg1duration, arg2year, LT);
+ assertCompareException(arg1duration, arg2dateTime, LT);
+ assertCompareException(arg1duration, arg2duration, LT);
+ assertCompareTrue(arg1duration, arg2duration, LT, false);
+ assertCompareException(arg1duration, arg2yearMonthDuration, LT);
+ assertCompareException(arg1duration, arg2yearMonthDuration, LT, false);
+ assertCompareException(arg1duration, arg2unknown, LT);
+
+ assertCompareException(arg1yearMonthDuration, arg2simple, LT);
+ assertCompareException(arg1yearMonthDuration, arg2en, LT);
+ assertCompareException(arg1yearMonthDuration, arg2string, LT);
+ assertCompareException(arg1yearMonthDuration, arg2int, LT);
+ assertCompareException(arg1yearMonthDuration, arg2year, LT);
+ assertCompareException(arg1yearMonthDuration, arg2dateTime, LT);
+ assertCompareException(arg1yearMonthDuration, arg2duration, LT);
+ assertCompareTrue(arg1yearMonthDuration, arg2duration, LT, false);
+ assertCompareException(arg1yearMonthDuration, arg2yearMonthDuration, LT);
+ assertCompareTrue(arg1yearMonthDuration, arg2yearMonthDuration, LT, false);
+ assertCompareException(arg1yearMonthDuration, arg2unknown, LT);
+ }
+
+ /**
+ * Assert that there is an exception as a result of comparing the two literals with the given operator.
+ *
+ * @param lit1 The left literal
+ * @param lit2 The right literal
+ * @param op The operator for the comparison
+ */
+ private void assertCompareException(Literal lit1, Literal lit2, CompareOp op) {
+ assertCompareException(lit1, lit2, op, true);
+ }
+
+ /**
+ * Assert that there is an exception as a result of comparing the two literals with the given operator.
+ *
+ * @param lit1 The left literal
+ * @param lit2 The right literal
+ * @param op The operator for the comparison
+ */
+ private void assertCompareException(Literal lit1, Literal lit2, CompareOp op, boolean strict) {
+ QueryEvaluationUtility.Result result = QueryEvaluationUtility.compareLiterals(lit1, lit2, op, strict);
+ assertSame(QueryEvaluationUtility.Result.incompatibleValueExpression, result);
+ }
+
+ private void assertCompareFalse(Literal lit1, Literal lit2, CompareOp op) {
+ assertCompareFalse(lit1, lit2, op, true);
+ }
+
+ /**
+ * Assert that there is no exception as a result of comparing the two literals with the given operator and it
+ * returns false.
+ *
+ * @param lit1 The left literal
+ * @param lit2 The right literal
+ * @param op The operator for the comparison
+ */
+ private void assertCompareFalse(Literal lit1, Literal lit2, CompareOp op, boolean strict) {
+ assertFalse("Compare did not return false for " + lit1.toString() + op.getSymbol() + lit2.toString(),
+ QueryEvaluationUtility.compareLiterals(lit1, lit2, op, strict).orElse(false));
+ }
+
+ private void assertCompareTrue(Literal lit1, Literal lit2, CompareOp op) {
+ assertCompareTrue(lit1, lit2, op, true);
+ }
+
+ /**
+ * Assert that there is no exception as a result of comparing the two literals with the given operator and it
+ * returns true.
+ *
+ * @param lit1 The left literal
+ * @param lit2 The right literal
+ * @param op The operator for the comparison
+ * @param strict boolean switch between strict and extended comparison
+ */
+ private void assertCompareTrue(Literal lit1, Literal lit2, CompareOp op, boolean strict) {
+ assertTrue("Compare did not return true for " + lit1.toString() + op.getSymbol() + lit2.toString(),
+ QueryEvaluationUtility.compareLiterals(lit1, lit2, op, strict).orElse(false));
+ }
+
+ /**
+ * Reporoduces GH-2760: an NPE has been thrown when comparing custom literal implementations
+ */
+ @Test
+ public void testCompareWithCustomLiterals() {
+ SimpleValueFactory vf = SimpleValueFactory.getInstance();
+ Literal left = vf.createLiteral(5);
+
+ Literal right = getCustomLiteral(vf.createLiteral(6));
+ // GH-2760: should not throw an NPE, simply try all avaliable comparator operators
+ for (CompareOp op : CompareOp.values()) {
+ QueryEvaluationUtility.compareLiterals(left, right, op, true);
+ QueryEvaluationUtility.compareLiterals(right, left, op, true);
+ }
+
+ }
+
+ /**
+ * Reporoduces GH-2760: an NPE has been thrown when comparing custom literal implementations
+ */
+ @Test
+ public void testCompareWithCustomLiteralsIncompatible() {
+ SimpleValueFactory vf = SimpleValueFactory.getInstance();
+ Literal left = vf.createLiteral("abc");
+
+ Literal right = getCustomLiteral(vf.createLiteral(6));
+ // GH-2760: should not throw an NPE, simply try all avaliable comparator operators
+ for (CompareOp op : CompareOp.values()) {
+ try {
+ QueryEvaluationUtility.compareLiterals(left, right, op, true);
+ } catch (ValueExprEvaluationException e) {
+ assertEquals("Unable to compare strings with other supported types", e.getMessage());
+ }
+ try {
+ QueryEvaluationUtility.compareLiterals(right, left, op, true);
+ } catch (ValueExprEvaluationException e) {
+ assertEquals("Unable to compare strings with other supported types", e.getMessage());
+ }
+ }
+ }
+
+ @Test
+ public void testCompareWithCustomLiteralsInditerminate() {
+ SimpleValueFactory vf = SimpleValueFactory.getInstance();
+ Literal left = vf.createLiteral("2000-01-01T12:00:00", XSD.DATETIME);
+
+ Literal right = getCustomLiteral(vf.createLiteral("1999-12-31T23:00:00Z", XSD.DATETIME));
+ // GH-2760: should not throw an NPE, simply try all avaliable comparator operators
+ for (CompareOp op : CompareOp.values()) {
+ try {
+ QueryEvaluationUtility.compareLiterals(left, right, op, true);
+ } catch (ValueExprEvaluationException e) {
+ assertEquals("Indeterminate result for date/time comparison", e.getMessage());
+ }
+ try {
+ QueryEvaluationUtility.compareLiterals(right, left, op, true);
+ } catch (ValueExprEvaluationException e) {
+ assertEquals("Indeterminate result for date/time comparison", e.getMessage());
+ }
+ }
+ }
+
+ @Test
+ public void testCompareCustomDatatypes() {
+ SimpleValueFactory vf = SimpleValueFactory.getInstance();
+ Literal left = vf.createLiteral(1);
+
+ Literal right = vf.createLiteral("I", vf.createIRI("http://example.org/romanNumeral"));
+ // GH-2760: should not throw an NPE, simply try all avaliable comparator operators
+ for (CompareOp op : CompareOp.values()) {
+ try {
+ QueryEvaluationUtility.compareLiterals(left, right, op, true);
+ } catch (ValueExprEvaluationException e) {
+ assertEquals("Unable to compare literals with unsupported types", e.getMessage());
+ }
+ try {
+ QueryEvaluationUtility.compareLiterals(right, left, op, true);
+ } catch (ValueExprEvaluationException e) {
+ assertEquals("Unable to compare literals with unsupported types", e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Reporoduces GH-2760: an NPE has been thrown when comparing custom literal implementations
+ */
+ @Test
+ public void testCompareWithOnlyCustomLiterals() {
+ SimpleValueFactory vf = SimpleValueFactory.getInstance();
+ Literal left = getCustomLiteral(vf.createLiteral(1));
+
+ Literal right = getCustomLiteral(vf.createLiteral(6));
+ // GH-2760: should not throw an NPE, simply try all avaliable comparator operators
+ for (CompareOp op : CompareOp.values()) {
+ QueryEvaluationUtility.compareLiterals(left, right, op, true);
+ }
+ }
+
+ private Literal getCustomLiteral(Literal nested) {
+ Literal right = new Literal() {
+
+ @Override
+ public String stringValue() {
+ return nested.stringValue();
+ }
+
+ @Override
+ public short shortValue() {
+ return nested.shortValue();
+ }
+
+ @Override
+ public long longValue() {
+ return nested.longValue();
+ }
+
+ @Override
+ public BigInteger integerValue() {
+ return nested.integerValue();
+ }
+
+ @Override
+ public int intValue() {
+ return nested.intValue();
+ }
+
+ @Override
+ public Optional getLanguage() {
+ return nested.getLanguage();
+ }
+
+ @Override
+ public String getLabel() {
+ return nested.getLabel();
+ }
+
+ @Override
+ public IRI getDatatype() {
+ return nested.getDatatype();
+ }
+
+ @Override
+ public float floatValue() {
+ return nested.floatValue();
+ }
+
+ @Override
+ public double doubleValue() {
+ return nested.doubleValue();
+ }
+
+ @Override
+ public BigDecimal decimalValue() {
+ return nested.decimalValue();
+ }
+
+ @Override
+ public XMLGregorianCalendar calendarValue() {
+ return nested.calendarValue();
+ }
+
+ @Override
+ public CoreDatatype getCoreDatatype() {
+ return nested.getCoreDatatype();
+ }
+
+ @Override
+ public byte byteValue() {
+ return nested.byteValue();
+ }
+
+ @Override
+ public boolean booleanValue() {
+ return nested.booleanValue();
+ }
+ };
+ return right;
+ }
+}
diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/XMLDatatypeMathUtilTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/XMLDatatypeMathUtilTest.java
index 7602fad37aa..c355d3c7c71 100644
--- a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/XMLDatatypeMathUtilTest.java
+++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/XMLDatatypeMathUtilTest.java
@@ -12,6 +12,7 @@
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.ValueFactory;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.junit.Test;
@@ -26,24 +27,27 @@ public class XMLDatatypeMathUtilTest {
@Test
public void testCompute() throws Exception {
Literal float1 = vf.createLiteral("12", XSD.INTEGER);
- Literal float2 = vf.createLiteral("2", XSD.INTEGER);
+ Literal float2 = vf.createLiteral("2", CoreDatatype.XSD.INTEGER);
Literal duration1 = vf.createLiteral("P1Y1M", XSD.YEARMONTHDURATION);
- Literal duration2 = vf.createLiteral("P1Y", XSD.YEARMONTHDURATION);
+ Literal duration2 = vf.createLiteral("P1Y", CoreDatatype.XSD.YEARMONTHDURATION);
Literal yearMonth1 = vf.createLiteral("2012-10", XSD.GYEARMONTH);
assertComputeEquals(vf.createLiteral("14", XSD.INTEGER), float1, float2, MathOp.PLUS);
- assertComputeEquals(vf.createLiteral("10", XSD.INTEGER), float1, float2, MathOp.MINUS);
+ assertComputeEquals(vf.createLiteral("10", CoreDatatype.XSD.INTEGER), float1, float2, MathOp.MINUS);
assertComputeEquals(vf.createLiteral("24", XSD.INTEGER), float1, float2, MathOp.MULTIPLY);
- assertComputeEquals(vf.createLiteral("6", XSD.DECIMAL), float1, float2, MathOp.DIVIDE);
+ assertComputeEquals(vf.createLiteral("6", CoreDatatype.XSD.DECIMAL), float1, float2, MathOp.DIVIDE);
assertComputeEquals(vf.createLiteral("P2Y1M", XSD.YEARMONTHDURATION), duration1, duration2, MathOp.PLUS);
- assertComputeEquals(vf.createLiteral("P0Y1M", XSD.YEARMONTHDURATION), duration1, duration2, MathOp.MINUS);
+ assertComputeEquals(vf.createLiteral("P0Y1M", CoreDatatype.XSD.YEARMONTHDURATION), duration1, duration2,
+ MathOp.MINUS);
- assertComputeEquals(vf.createLiteral("P12Y", XSD.YEARMONTHDURATION), float1, duration2, MathOp.MULTIPLY);
+ assertComputeEquals(vf.createLiteral("P12Y", CoreDatatype.XSD.YEARMONTHDURATION), float1, duration2,
+ MathOp.MULTIPLY);
assertComputeEquals(vf.createLiteral("P12Y", XSD.YEARMONTHDURATION), duration2, float1, MathOp.MULTIPLY);
assertComputeEquals(vf.createLiteral("2013-11", XSD.GYEARMONTH), yearMonth1, duration1, MathOp.PLUS);
- assertComputeEquals(vf.createLiteral("2011-09", XSD.GYEARMONTH), yearMonth1, duration1, MathOp.MINUS);
+ assertComputeEquals(vf.createLiteral("2011-09", CoreDatatype.XSD.GYEARMONTH), yearMonth1, duration1,
+ MathOp.MINUS);
assertComputeEquals(vf.createLiteral("2013-11", XSD.GYEARMONTH), duration1, yearMonth1, MathOp.PLUS);
}
diff --git a/core/repository/api/src/test/java/org/eclipse/rdf4j/repository/util/RDFLoaderTest.java b/core/repository/api/src/test/java/org/eclipse/rdf4j/repository/util/RDFLoaderTest.java
index 83665274910..8ce5a8cccc1 100644
--- a/core/repository/api/src/test/java/org/eclipse/rdf4j/repository/util/RDFLoaderTest.java
+++ b/core/repository/api/src/test/java/org/eclipse/rdf4j/repository/util/RDFLoaderTest.java
@@ -50,14 +50,14 @@
/**
* Unit tests for {@link RDFLoader}.
- *
+ *
* @author Manuel Fiorelli
*
*/
public class RDFLoaderTest {
@ClassRule
- public static WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort().dynamicHttpsPort());
+ public static WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort());
@Test
public void testTurtleJavaResource() throws Exception {
@@ -172,7 +172,7 @@ public void testNonInformationResource() throws Exception {
try {
stubFor(get("/Socrates")
.willReturn(
- permanentRedirect("https://localhost:" + wireMockRule.httpsPort() + "/Socrates.ttl")));
+ permanentRedirect("http://localhost:" + wireMockRule.port() + "/Socrates.ttl")));
stubFor(get("/Socrates.ttl")
.willReturn(aResponse()
diff --git a/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFParserHelper.java b/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFParserHelper.java
index 0fa61082af9..c1012cafeca 100644
--- a/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFParserHelper.java
+++ b/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFParserHelper.java
@@ -12,9 +12,9 @@
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.ValueFactory;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.util.LiteralUtilException;
import org.eclipse.rdf4j.model.vocabulary.RDF;
-import org.eclipse.rdf4j.model.vocabulary.XSD;
import org.eclipse.rdf4j.rio.DatatypeHandler;
import org.eclipse.rdf4j.rio.LanguageHandler;
import org.eclipse.rdf4j.rio.ParseErrorListener;
@@ -198,9 +198,13 @@ public static final Literal createLiteral(String label, String lang, IRI datatyp
}
// Backup for unnormalised datatype literal creation
else if (workingDatatype != null) {
- result = valueFactory.createLiteral(workingLabel, workingDatatype);
+ CoreDatatype coreDatatype = CoreDatatype.from(workingDatatype);
+
+ result = valueFactory.createLiteral(workingLabel,
+ coreDatatype != CoreDatatype.NONE ? coreDatatype.getIri() : workingDatatype, coreDatatype);
+
} else {
- result = valueFactory.createLiteral(workingLabel, XSD.STRING);
+ result = valueFactory.createLiteral(workingLabel, CoreDatatype.XSD.STRING);
}
} catch (Exception e) {
reportFatalError(e, lineNo, columnNo, errListener);
diff --git a/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFStarDecodingValueFactory.java b/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFStarDecodingValueFactory.java
index 42a9dcdf94d..ede66d08356 100644
--- a/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFStarDecodingValueFactory.java
+++ b/core/rio/api/src/main/java/org/eclipse/rdf4j/rio/helpers/RDFStarDecodingValueFactory.java
@@ -78,6 +78,11 @@ public Literal createLiteral(String label, CoreDatatype datatype) {
return delegate.createLiteral(label, datatype);
}
+ @Override
+ public Literal createLiteral(String label, IRI datatype, CoreDatatype coreDatatype) {
+ return delegate.createLiteral(label, datatype, coreDatatype);
+ }
+
@Override
public Literal createLiteral(boolean value) {
return delegate.createLiteral(value);
diff --git a/core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLWriter.java b/core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLWriter.java
index 016bbd74511..b592539ede0 100644
--- a/core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLWriter.java
+++ b/core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLWriter.java
@@ -26,6 +26,7 @@
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.Value;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.util.Literals;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.model.vocabulary.XSD;
@@ -298,14 +299,15 @@ protected void consumeStatement(Statement st) {
if (Literals.isLanguageLiteral(objLit)) {
writeAttribute("xml:lang", objLit.getLanguage().get());
} else {
- IRI datatype = objLit.getDatatype();
+ CoreDatatype coreDatatype = objLit.getCoreDatatype();
+
// Check if datatype is rdf:XMLLiteral
- isXMLLiteral = datatype.equals(RDF.XMLLITERAL);
+ isXMLLiteral = coreDatatype == CoreDatatype.RDF.XMLLITERAL;
if (isXMLLiteral) {
writeAttribute(RDF.NAMESPACE, "parseType", "Literal");
- } else if (!datatype.equals(XSD.STRING)) {
- writeAttribute(RDF.NAMESPACE, "datatype", datatype.toString());
+ } else if (coreDatatype != CoreDatatype.XSD.STRING) {
+ writeAttribute(RDF.NAMESPACE, "datatype", objLit.getDatatype().toString());
}
}
diff --git a/core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/util/RDFXMLPrettyWriter.java b/core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/util/RDFXMLPrettyWriter.java
index cd71b17096e..9163aed09a3 100644
--- a/core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/util/RDFXMLPrettyWriter.java
+++ b/core/rio/rdfxml/src/main/java/org/eclipse/rdf4j/rio/rdfxml/util/RDFXMLPrettyWriter.java
@@ -23,6 +23,7 @@
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.Value;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.model.util.Literals;
import org.eclipse.rdf4j.model.vocabulary.RDF;
@@ -455,9 +456,9 @@ private void writeAbbreviatedPredicate(IRI pred, Value obj) throws IOException,
} else if (obj instanceof Literal) {
Literal objLit = (Literal) obj;
// datatype attribute
- IRI datatype = objLit.getDatatype();
+ CoreDatatype datatype = objLit.getCoreDatatype();
// Check if datatype is rdf:XMLLiteral
- boolean isXmlLiteral = datatype.equals(RDF.XMLLITERAL);
+ boolean isXmlLiteral = datatype == CoreDatatype.RDF.XMLLITERAL;
// language attribute
if (Literals.isLanguageLiteral(objLit)) {
@@ -466,7 +467,7 @@ private void writeAbbreviatedPredicate(IRI pred, Value obj) throws IOException,
if (isXmlLiteral) {
writeAttribute(RDF.NAMESPACE, "parseType", "Literal");
} else {
- writeAttribute(RDF.NAMESPACE, "datatype", datatype.toString());
+ writeAttribute(RDF.NAMESPACE, "datatype", objLit.getDatatype().toString());
}
}
diff --git a/core/rio/rdfxml/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserTest.java b/core/rio/rdfxml/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserTest.java
index 6a59e1dc01c..0729f18d44a 100644
--- a/core/rio/rdfxml/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserTest.java
+++ b/core/rio/rdfxml/src/test/java/org/eclipse/rdf4j/rio/rdfxml/RDFXMLParserTest.java
@@ -16,6 +16,7 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.io.StringReader;
import java.net.URL;
import java.util.Collection;
import java.util.Iterator;
@@ -31,6 +32,7 @@
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.rio.RDFParseException;
import org.eclipse.rdf4j.rio.RDFParser;
+import org.eclipse.rdf4j.rio.Rio;
import org.eclipse.rdf4j.rio.helpers.ParseErrorCollector;
import org.eclipse.rdf4j.rio.helpers.StatementCollector;
import org.eclipse.rdf4j.rio.helpers.XMLParserSettings;
@@ -217,7 +219,7 @@ public void testInsertUsedContextPrefixes() {
" 0\n" +
" 0\n" +
" \"^^)";
- String s2 = "(http://mycorp.example.com/papers/NobelPaper1, http://purl.org/metadata/dublin_core#Creator, \"David Hume\")";
+ String s2 = "(http://mycorp.example.com/papers/NobelPaper1, http://purl.org/metadata/dublin_core#Creator, \"David Hume\"^^)";
expectedLiteral[0] = s1;
expectedLiteral[1] = s2;
@@ -226,5 +228,6 @@ public void testInsertUsedContextPrefixes() {
assertEquals(s.toString(), expectedLiteral[ind]);
ind += 1;
}
+
}
}
diff --git a/core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/model/LmdbLiteral.java b/core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/model/LmdbLiteral.java
index b1b510293ad..fb8bfe6e363 100644
--- a/core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/model/LmdbLiteral.java
+++ b/core/sail/lmdb/src/main/java/org/eclipse/rdf4j/sail/lmdb/model/LmdbLiteral.java
@@ -107,6 +107,9 @@ public LmdbLiteral(ValueStoreRevision revision, String label, IRI datatype, long
public LmdbLiteral(ValueStoreRevision revision, String label, IRI datatype, CoreDatatype coreDatatype,
long internalID) {
this.label = label;
+ assert datatype != null;
+ assert coreDatatype != null;
+ assert coreDatatype == CoreDatatype.NONE || coreDatatype.getIri() == datatype;
this.datatype = datatype;
this.coreDatatype = coreDatatype;
setInternalID(internalID, revision);
@@ -150,8 +153,9 @@ public IRI getDatatype() {
@Override
public CoreDatatype getCoreDatatype() {
init();
- if (coreDatatype == null)
+ if (coreDatatype == null) {
coreDatatype = CoreDatatype.from(datatype);
+ }
return coreDatatype;
}
diff --git a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/CalendarMemLiteral.java b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/CalendarMemLiteral.java
index 4693b366da3..48ad302ba2d 100644
--- a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/CalendarMemLiteral.java
+++ b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/CalendarMemLiteral.java
@@ -12,6 +12,7 @@
import javax.xml.datatype.XMLGregorianCalendar;
import org.eclipse.rdf4j.model.IRI;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
/**
@@ -39,7 +40,7 @@ public CalendarMemLiteral(Object creator, XMLGregorianCalendar calendar) {
}
public CalendarMemLiteral(Object creator, String label, XMLGregorianCalendar calendar) {
- this(creator, label, XMLDatatypeUtil.qnameToURI(calendar.getXMLSchemaType()), calendar);
+ this(creator, label, XMLDatatypeUtil.qnameToCoreDatatype(calendar.getXMLSchemaType()), calendar);
}
public CalendarMemLiteral(Object creator, String label, IRI datatype, XMLGregorianCalendar calendar) {
@@ -47,6 +48,11 @@ public CalendarMemLiteral(Object creator, String label, IRI datatype, XMLGregori
this.calendar = calendar;
}
+ public CalendarMemLiteral(Object creator, String label, CoreDatatype datatype, XMLGregorianCalendar calendar) {
+ super(creator, label, datatype);
+ this.calendar = calendar;
+ }
+
/*---------*
* Methods *
*---------*/
diff --git a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/DecimalMemLiteral.java b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/DecimalMemLiteral.java
index 53b100c1a3a..9004c7488e3 100644
--- a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/DecimalMemLiteral.java
+++ b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/DecimalMemLiteral.java
@@ -11,6 +11,7 @@
import java.math.BigInteger;
import org.eclipse.rdf4j.model.IRI;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.vocabulary.XSD;
/**
@@ -45,6 +46,11 @@ public DecimalMemLiteral(Object creator, String label, BigDecimal value, IRI dat
this.value = value;
}
+ public DecimalMemLiteral(Object creator, String label, BigDecimal value, CoreDatatype datatype) {
+ super(creator, label, datatype);
+ this.value = value;
+ }
+
/*---------*
* Methods *
*---------*/
diff --git a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/IntegerMemLiteral.java b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/IntegerMemLiteral.java
index 296832f7702..d8d63fdcd33 100644
--- a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/IntegerMemLiteral.java
+++ b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/IntegerMemLiteral.java
@@ -11,6 +11,7 @@
import java.math.BigInteger;
import org.eclipse.rdf4j.model.IRI;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.vocabulary.XSD;
/**
@@ -33,18 +34,27 @@ public class IntegerMemLiteral extends MemLiteral {
*--------------*/
public IntegerMemLiteral(Object creator, BigInteger value) {
- this(creator, value, XSD.INTEGER);
+ this(creator, value, CoreDatatype.XSD.INTEGER);
}
public IntegerMemLiteral(Object creator, BigInteger value, IRI datatype) {
this(creator, value.toString(), value, datatype);
}
+ public IntegerMemLiteral(Object creator, BigInteger value, CoreDatatype datatype) {
+ this(creator, value.toString(), value, datatype);
+ }
+
public IntegerMemLiteral(Object creator, String label, BigInteger value, IRI datatype) {
super(creator, label, datatype);
this.value = value;
}
+ public IntegerMemLiteral(Object creator, String label, BigInteger value, CoreDatatype datatype) {
+ super(creator, label, datatype);
+ this.value = value;
+ }
+
/*---------*
* Methods *
*---------*/
diff --git a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemLiteral.java b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemLiteral.java
index 611420854bd..5b36c9fe2ab 100644
--- a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemLiteral.java
+++ b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemLiteral.java
@@ -8,6 +8,7 @@
package org.eclipse.rdf4j.sail.memory.model;
import org.eclipse.rdf4j.model.IRI;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.impl.SimpleLiteral;
import org.eclipse.rdf4j.model.vocabulary.XSD;
@@ -73,6 +74,16 @@ public MemLiteral(Object creator, String label, IRI datatype) {
this.creator = creator;
}
+ public MemLiteral(Object creator, String label, IRI datatype, CoreDatatype coreDatatype) {
+ super(label, datatype, coreDatatype);
+ this.creator = creator;
+ }
+
+ public MemLiteral(Object creator, String label, CoreDatatype datatype) {
+ super(label, datatype);
+ this.creator = creator;
+ }
+
/*---------*
* Methods *
*---------*/
diff --git a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemValueFactory.java b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemValueFactory.java
index 07d399fc697..f6609c6ba18 100644
--- a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemValueFactory.java
+++ b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/MemValueFactory.java
@@ -19,11 +19,10 @@
import org.eclipse.rdf4j.model.Triple;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.base.AbstractValueFactory;
-import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.util.Literals;
import org.eclipse.rdf4j.model.util.URIUtil;
import org.eclipse.rdf4j.model.util.Values;
-import org.eclipse.rdf4j.model.vocabulary.XSD;
/**
* A factory for MemValue objects that keeps track of created objects to prevent the creation of duplicate objects,
@@ -285,37 +284,38 @@ public MemBNode getOrCreateMemBNode(BNode bnode) {
public MemLiteral getOrCreateMemLiteral(Literal literal) {
return literalRegistry.getOrAdd(literal, () -> {
String label = literal.getLabel();
- IRI datatype = literal.getDatatype();
- MemLiteral memLiteral;
+ CoreDatatype coreDatatype = literal.getCoreDatatype();
+ IRI datatype = coreDatatype != CoreDatatype.NONE ? coreDatatype.getIri() : literal.getDatatype();
if (Literals.isLanguageLiteral(literal)) {
- memLiteral = new MemLiteral(this, label, literal.getLanguage().get());
+ return new MemLiteral(this, label, literal.getLanguage().get());
} else {
try {
- if (XMLDatatypeUtil.isIntegerDatatype(datatype)) {
- memLiteral = new IntegerMemLiteral(this, label, literal.integerValue(), datatype);
- } else if (datatype.equals(XSD.DECIMAL)) {
- memLiteral = new DecimalMemLiteral(this, label, literal.decimalValue(), datatype);
- } else if (datatype.equals(XSD.FLOAT)) {
- memLiteral = new NumericMemLiteral(this, label, literal.floatValue(), datatype);
- } else if (datatype.equals(XSD.DOUBLE)) {
- memLiteral = new NumericMemLiteral(this, label, literal.doubleValue(), datatype);
- } else if (datatype.equals(XSD.BOOLEAN)) {
- memLiteral = new BooleanMemLiteral(this, label, literal.booleanValue());
- } else if (datatype.equals(XSD.DATETIME)) {
- memLiteral = new CalendarMemLiteral(this, label, datatype, literal.calendarValue());
- } else if (datatype.equals(XSD.DATETIMESTAMP)) {
- memLiteral = new CalendarMemLiteral(this, label, datatype, literal.calendarValue());
- } else {
- memLiteral = new MemLiteral(this, label, datatype);
+ if (coreDatatype.isXSDDatatype()) {
+ if (((CoreDatatype.XSD) coreDatatype).isIntegerDatatype()) {
+ return new IntegerMemLiteral(this, label, literal.integerValue(), coreDatatype);
+ } else if (coreDatatype == CoreDatatype.XSD.DECIMAL) {
+ return new DecimalMemLiteral(this, label, literal.decimalValue(), coreDatatype);
+ } else if (coreDatatype == CoreDatatype.XSD.FLOAT) {
+ return new NumericMemLiteral(this, label, literal.floatValue(), coreDatatype);
+ } else if (coreDatatype == CoreDatatype.XSD.DOUBLE) {
+ return new NumericMemLiteral(this, label, literal.doubleValue(), coreDatatype);
+ } else if (coreDatatype == CoreDatatype.XSD.BOOLEAN) {
+ return new BooleanMemLiteral(this, label, literal.booleanValue());
+ } else if (coreDatatype == CoreDatatype.XSD.DATETIME) {
+ return new CalendarMemLiteral(this, label, coreDatatype, literal.calendarValue());
+ } else if (coreDatatype == CoreDatatype.XSD.DATETIMESTAMP) {
+ return new CalendarMemLiteral(this, label, coreDatatype, literal.calendarValue());
+ }
}
+
+ return new MemLiteral(this, label, datatype, coreDatatype);
+
} catch (IllegalArgumentException e) {
// Unable to parse literal label to primitive type
- memLiteral = new MemLiteral(this, label, datatype);
+ return new MemLiteral(this, label, datatype);
}
}
-
- return memLiteral;
});
}
@@ -374,6 +374,11 @@ public Literal createLiteral(String value, IRI datatype) {
return getOrCreateMemLiteral(super.createLiteral(value, datatype));
}
+ @Override
+ public Literal createLiteral(String value, CoreDatatype datatype) {
+ return getOrCreateMemLiteral(super.createLiteral(value, datatype));
+ }
+
@Override
public Literal createLiteral(boolean value) {
MemLiteral newLiteral = new BooleanMemLiteral(this, value);
diff --git a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/NumericMemLiteral.java b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/NumericMemLiteral.java
index 157decbe282..18182470758 100644
--- a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/NumericMemLiteral.java
+++ b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/model/NumericMemLiteral.java
@@ -8,6 +8,7 @@
package org.eclipse.rdf4j.sail.memory.model;
import org.eclipse.rdf4j.model.IRI;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
import org.eclipse.rdf4j.model.vocabulary.XSD;
@@ -36,6 +37,11 @@ public NumericMemLiteral(Object creator, String label, Number number, IRI dataty
this.number = number;
}
+ public NumericMemLiteral(Object creator, String label, Number number, CoreDatatype datatype) {
+ super(creator, label, datatype);
+ this.number = number;
+ }
+
public NumericMemLiteral(Object creator, Number number, IRI datatype) {
this(creator, XMLDatatypeUtil.toString(number), number, datatype);
}
diff --git a/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/benchmark/OOMBenchmark.java b/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/benchmark/OOMBenchmark.java
new file mode 100644
index 00000000000..baa380e4432
--- /dev/null
+++ b/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/benchmark/OOMBenchmark.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2022 Eclipse RDF4J contributors.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Distribution License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *******************************************************************************/
+
+package org.eclipse.rdf4j.sail.memory.benchmark;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.commons.io.IOUtils;
+import org.eclipse.rdf4j.common.transaction.IsolationLevels;
+import org.eclipse.rdf4j.model.Statement;
+import org.eclipse.rdf4j.model.Value;
+import org.eclipse.rdf4j.query.BindingSet;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.ValueComparator;
+import org.eclipse.rdf4j.repository.sail.SailRepository;
+import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
+import org.eclipse.rdf4j.rio.RDFFormat;
+import org.eclipse.rdf4j.sail.memory.MemoryStore;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+/**
+ * This is a special benchmark that counts the number of benchmark iterations that can be run before running out of
+ * memory. The benchmarks will all fail because they will all eventually run out of memory because the Epsilon garbage
+ * collector is a no-op collector. Each benchmark prints the number of iterations they manage before running out of
+ * memory, this is the measurement that we care about. A higher number of iterations means that we produce less garbage.
+ * It doesn't necessarily mean that we use less memory.
+ *
+ * @author Håvard Ottestad
+ */
+@State(Scope.Benchmark)
+@Warmup(iterations = 0)
+@BenchmarkMode({ Mode.AverageTime })
+@Fork(value = 1, jvmArgs = { "-Xms8G", "-Xmx8G", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseEpsilonGC",
+ "-XX:+AlwaysPreTouch" })
+@Measurement(iterations = 1, time = 99999999)
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+public class OOMBenchmark {
+
+ private SailRepository repository;
+
+ private static final String query9;
+ int count = 0;
+ List valuesList;
+
+ static {
+ try {
+ query9 = IOUtils.toString(getResourceAsStream("benchmarkFiles/query9.qr"), StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void main(String[] args) throws RunnerException {
+ Options opt = new OptionsBuilder()
+ .include("OOMBenchmark.*") // adapt to run other benchmark tests
+ .forks(1)
+ .build();
+
+ new Runner(opt).run();
+ }
+
+ @Setup(Level.Trial)
+ public void setup() throws IOException, InterruptedException {
+
+ repository = new SailRepository(new MemoryStore());
+
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ connection.begin(IsolationLevels.NONE);
+ connection.add(getResourceAsStream("benchmarkFiles/datagovbe-valid.ttl"), "", RDFFormat.TURTLE);
+ connection.commit();
+ }
+
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ try (Stream stream = connection.getStatements(null, null, null, false).stream()) {
+ valuesList = new ArrayList<>((int) stream.count());
+ }
+
+ try (Stream stream = connection.getStatements(null, null, null, false).stream()) {
+ stream
+ .map(Statement::getObject)
+ .sorted(new ValueComparator())
+ .forEach(valuesList::add);
+ }
+
+ }
+
+ }
+
+ @Setup(Level.Iteration)
+ public void setupIteration() {
+ count = 0;
+ }
+
+ @TearDown(Level.Trial)
+ public void afterClass() {
+
+ repository.shutDown();
+
+ }
+
+ @Benchmark
+ public List sortAllObjectsWithSparql() {
+
+ try (SailRepositoryConnection connection = repository.getConnection()) {
+ try (Stream stream = connection
+ .prepareTupleQuery(query9)
+ .evaluate()
+ .stream()) {
+ List collect = stream.limit(1).collect(Collectors.toList());
+ incrementAndPrintCount();
+ return collect;
+ }
+ }
+ }
+
+ @Benchmark
+ public Value sortDirectly() {
+
+ Collections.shuffle(valuesList, new Random(47583672));
+
+ valuesList.sort(new ValueComparator());
+ incrementAndPrintCount();
+
+ return valuesList.get(0);
+
+ }
+
+ private void incrementAndPrintCount() {
+ System.out.println("\nCount: " + (++count));
+ }
+
+ private static InputStream getResourceAsStream(String name) {
+ return OOMBenchmark.class.getClassLoader().getResourceAsStream(name);
+ }
+
+}
diff --git a/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/benchmark/SortBenchmark.java b/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/benchmark/SortBenchmark.java
index 4d4669dbbb5..3989950075a 100644
--- a/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/benchmark/SortBenchmark.java
+++ b/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/benchmark/SortBenchmark.java
@@ -40,21 +40,18 @@
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
-import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
-import org.openjdk.jmh.runner.options.Options;
-import org.openjdk.jmh.runner.options.OptionsBuilder;
/**
* @author Håvard Ottestad
*/
@State(Scope.Benchmark)
-@Warmup(iterations = 5)
+@Warmup(iterations = 0)
@BenchmarkMode({ Mode.AverageTime })
// use G1GC because the workload is multi-threaded
-@Fork(value = 1, jvmArgs = { "-Xms400M", "-Xmx400M", "-XX:+UseG1GC" })
-//@Fork(value = 1, jvmArgs = {"-Xms8G", "-Xmx8G", "-Xmn4G", "-XX:+UseSerialGC", "-XX:+UnlockCommercialFeatures", "-XX:StartFlightRecording=delay=60s,duration=120s,filename=recording.jfr,settings=profile", "-XX:FlightRecorderOptions=samplethreads=true,stackdepth=1024", "-XX:+UnlockDiagnosticVMOptions", "-XX:+DebugNonSafepoints"})
-@Measurement(iterations = 5)
+@Fork(value = 1, jvmArgs = { "-Xms400M", "-Xmx400M", "-XX:+UseSerialGC" })
+//@Fork(value = 1, jvmArgs = {"-Xms400M", "-Xmx400M", "-XX:+UseSerialGC", "-XX:StartFlightRecording=delay=60s,duration=240s,filename=recording.jfr,settings=profile", "-XX:FlightRecorderOptions=samplethreads=true,stackdepth=1024", "-XX:+UnlockDiagnosticVMOptions", "-XX:+DebugNonSafepoints"})
+@Measurement(iterations = 100)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class SortBenchmark {
@@ -73,18 +70,19 @@ public class SortBenchmark {
List valuesList;
- public static void main(String[] args) throws RunnerException {
- Options opt = new OptionsBuilder()
- .include("SortBenchmark.*") // adapt to run other benchmark tests
- // .addProfiler("stack", "lines=20;period=1;top=20")
- .forks(1)
- .build();
-
- new Runner(opt).run();
+ public static void main(String[] args) throws RunnerException, IOException, InterruptedException {
+ SortBenchmark sortBenchmark = new SortBenchmark();
+ sortBenchmark.setup();
+ System.out.println("sort");
+ while (true) {
+ sortBenchmark.sortDirectly();
+ System.out.println(".");
+ }
+// sortBenchmark.tearDown();
}
@Setup(Level.Trial)
- public void beforeClass() throws IOException, InterruptedException {
+ public void setup() throws IOException, InterruptedException {
repository = new SailRepository(new MemoryStore());
@@ -109,7 +107,7 @@ private static InputStream getResourceAsStream(String name) {
}
@TearDown(Level.Trial)
- public void afterClass() {
+ public void tearDown() {
repository.shutDown();
diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/LiteralComparatorFilter.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/LiteralComparatorFilter.java
index be284125954..e6a992ca6e5 100644
--- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/LiteralComparatorFilter.java
+++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/planNodes/LiteralComparatorFilter.java
@@ -13,8 +13,7 @@
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.query.algebra.Compare;
-import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
-import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;
+import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtility;
/**
* @author Håvard Ottestad
@@ -35,13 +34,7 @@ public LiteralComparatorFilter(PlanNode parent, Literal compareTo, Compare.Compa
@Override
boolean checkTuple(ValidationTuple t) {
Value literal = t.getValue();
-
- try {
- return QueryEvaluationUtil.compare(compareTo, literal, this.compareOp);
- } catch (ValueExprEvaluationException e) {
- return false;
- }
-
+ return QueryEvaluationUtility.compare(compareTo, literal, this.compareOp).orElse(false);
}
@Override
diff --git a/core/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/ParseDate.java b/core/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/ParseDate.java
index 77a4775e7ac..92535b64cf1 100644
--- a/core/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/ParseDate.java
+++ b/core/spin/src/main/java/org/eclipse/rdf4j/spin/function/spif/ParseDate.java
@@ -89,7 +89,7 @@ protected Value evaluate(ValueFactory valueFactory, Value arg1, Value arg2) thro
}
}
- return valueFactory.createLiteral(dateValue, XMLDatatypeUtil.qnameToURI(dateType));
+ return valueFactory.createLiteral(dateValue, XMLDatatypeUtil.qnameToCoreDatatype(dateType));
}
static final class FieldAwareGregorianCalendar extends GregorianCalendar {
diff --git a/testsuites/rio/src/main/java/org/eclipse/rdf4j/testsuite/rio/rdfxml/RDFXMLParserTestCase.java b/testsuites/rio/src/main/java/org/eclipse/rdf4j/testsuite/rio/rdfxml/RDFXMLParserTestCase.java
index 220f401d94b..521b303eabc 100644
--- a/testsuites/rio/src/main/java/org/eclipse/rdf4j/testsuite/rio/rdfxml/RDFXMLParserTestCase.java
+++ b/testsuites/rio/src/main/java/org/eclipse/rdf4j/testsuite/rio/rdfxml/RDFXMLParserTestCase.java
@@ -9,12 +9,13 @@
import java.io.IOException;
import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashSet;
+import java.util.Objects;
import java.util.Set;
+import java.util.stream.Collectors;
import javax.xml.parsers.ParserConfigurationException;
@@ -24,6 +25,7 @@
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Statement;
+import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.model.util.Models;
import org.eclipse.rdf4j.model.vocabulary.RDF;
@@ -53,11 +55,11 @@ public abstract class RDFXMLParserTestCase {
* Constants *
*-----------*/
- private static String W3C_TESTS_DIR = "http://www.w3.org/2000/10/rdf-tests/rdfcore/";
+ private static final String W3C_TESTS_DIR = "http://www.w3.org/2000/10/rdf-tests/rdfcore/";
- private static String LOCAL_TESTS_DIR = "/testcases/rdfxml/";
+ private static final String LOCAL_TESTS_DIR = "/testcases/rdfxml/";
- private static String W3C_MANIFEST_FILE = W3C_TESTS_DIR + "Manifest.rdf";
+ private static final String W3C_MANIFEST_FILE = W3C_TESTS_DIR + "Manifest.rdf";
/*--------------------*
* Static initializer *
@@ -140,9 +142,9 @@ private class PositiveParserTest extends TestCase {
* Variables *
*-----------*/
- private String inputURL;
+ private final String inputURL;
- private String outputURL;
+ private final String outputURL;
/*--------------*
* Constructors *
@@ -170,9 +172,9 @@ protected void runTest() throws Exception {
StatementCollector inputCollector = new StatementCollector(inputCollection);
rdfxmlParser.setRDFHandler(inputCollector);
- InputStream in = resolveURL(inputURL).openStream();
- rdfxmlParser.parse(in, base(inputURL));
- in.close();
+ try (InputStream in = resolveURL(inputURL).openStream()) {
+ rdfxmlParser.parse(in, base(inputURL));
+ }
// Parse expected output data
NTriplesParser ntriplesParser = new NTriplesParser();
@@ -184,24 +186,18 @@ protected void runTest() throws Exception {
StatementCollector outputCollector = new StatementCollector(outputCollection);
ntriplesParser.setRDFHandler(outputCollector);
- in = resolveURL(outputURL).openStream();
- ntriplesParser.parse(in, base(inputURL));
- in.close();
+ try (InputStream in = resolveURL(outputURL).openStream()) {
+ ntriplesParser.parse(in, base(inputURL));
+ }
// Check equality of the two models
if (!Models.isomorphic(inputCollection, outputCollection)) {
- StringBuilder sb = new StringBuilder(1024);
- sb.append("models not equal\n");
- sb.append("Expected:\n");
- for (Statement st : outputCollection) {
- sb.append(st).append("\n");
- }
- sb.append("Actual:\n");
- for (Statement st : inputCollection) {
- sb.append(st).append("\n");
- }
- fail(sb.toString());
+ String expected = outputCollection.stream().map(Objects::toString).collect(Collectors.joining());
+ String actual = inputCollection.stream().map(Objects::toString).collect(Collectors.joining("\n"));
+
+ assertEquals(expected, actual);
+
}
}
@@ -217,7 +213,7 @@ private class NegativeParserTest extends TestCase {
* Variables *
*-----------*/
- private String inputURL;
+ private final String inputURL;
/*--------------*
* Constructors *
@@ -260,7 +256,7 @@ protected void runTest() {
private static class CanonXMLValueFactory extends SimpleValueFactory {
- private Canonicalizer c14n;
+ private final Canonicalizer c14n;
public CanonXMLValueFactory() throws InvalidCanonicalizerException, ParserConfigurationException {
org.apache.xml.security.Init.init();
@@ -271,25 +267,44 @@ public CanonXMLValueFactory() throws InvalidCanonicalizerException, ParserConfig
@Override
public Literal createLiteral(String value, IRI datatype) {
if (RDF.XMLLITERAL.equals(datatype)) {
- // Canonicalize the literal value
- try {
- value = new String(c14n.canonicalize(value.getBytes(StandardCharsets.UTF_8)),
- StandardCharsets.UTF_8);
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e);
- } catch (CanonicalizationException | SAXException e) {
- // ignore
- } catch (ParserConfigurationException e) {
- throw new RuntimeException(e);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- // ignore
+ value = canonicalizeXmlLiteral(value);
+ }
+
+ return super.createLiteral(value, datatype);
+ }
+ @Override
+ public Literal createLiteral(String value, CoreDatatype datatype) {
+ if (datatype == CoreDatatype.RDF.XMLLITERAL) {
+ value = canonicalizeXmlLiteral(value);
}
return super.createLiteral(value, datatype);
}
+
+ @Override
+ public Literal createLiteral(String value, IRI datatype, CoreDatatype coreDatatype) {
+ if (coreDatatype == CoreDatatype.RDF.XMLLITERAL) {
+ assert RDF.XMLLITERAL.equals(datatype);
+ value = canonicalizeXmlLiteral(value);
+ } else {
+ assert !RDF.XMLLITERAL.equals(datatype);
+ }
+
+ return super.createLiteral(value, datatype, coreDatatype);
+ }
+
+ private String canonicalizeXmlLiteral(String value) {
+ // Canonicalize the literal value
+ try {
+ return new String(c14n.canonicalize(value.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
+ } catch (ParserConfigurationException | IOException e) {
+ throw new RuntimeException(e);
+ } catch (CanonicalizationException | SAXException e) {
+ return value;
+ }
+ }
+
}
private static URL url(String uri) throws MalformedURLException {