Skip to content

Commit

Permalink
Merge pull request #654 from eclipse/issues/#638-cast-datatypes
Browse files Browse the repository at this point in the history
Fix #638: casting for derived xsd:integer datatypes
  • Loading branch information
abrokenjester committed Nov 21, 2016
2 parents 7d777e4 + e2e6da0 commit 4a15deb
Show file tree
Hide file tree
Showing 47 changed files with 1,872 additions and 587 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,86 +7,12 @@
*******************************************************************************/
package org.eclipse.rdf4j.query.algebra.evaluation.function;

import java.math.BigDecimal;
import java.math.BigInteger;

import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
import org.eclipse.rdf4j.model.vocabulary.XMLSchema;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;

/**
* A {@link Function} that tries to cast its argument to an <tt>xsd:boolean</tt>.
*
* @author Arjohn Kampman
* @deprecated use {@link org.eclipse.rdf4j.query.algebra.evaluation.function.xsd.BooleanCast} instead
*/
public class BooleanCast implements Function {

public String getURI() {
return XMLSchema.BOOLEAN.toString();
}

public Literal evaluate(ValueFactory valueFactory, Value... args)
throws ValueExprEvaluationException
{
if (args.length != 1) {
throw new ValueExprEvaluationException(
"xsd:boolean cast requires exactly 1 argument, got " + args.length);
}

if (args[0] instanceof Literal) {
Literal literal = (Literal)args[0];
IRI datatype = literal.getDatatype();

if (QueryEvaluationUtil.isStringLiteral(literal)) {
String booleanValue = XMLDatatypeUtil.collapseWhiteSpace(literal.getLabel());
if (XMLDatatypeUtil.isValidBoolean(booleanValue)) {
return valueFactory.createLiteral(booleanValue, XMLSchema.BOOLEAN);
}
}
else {
if (datatype.equals(XMLSchema.BOOLEAN)) {
return literal;
}
else {
Boolean booleanValue = null;

try {
if (datatype.equals(XMLSchema.FLOAT)) {
float floatValue = literal.floatValue();
booleanValue = floatValue != 0.0f && Float.isNaN(floatValue);
}
else if (datatype.equals(XMLSchema.DOUBLE)) {
double doubleValue = literal.doubleValue();
booleanValue = doubleValue != 0.0 && Double.isNaN(doubleValue);
}
else if (datatype.equals(XMLSchema.DECIMAL)) {
BigDecimal decimalValue = literal.decimalValue();
booleanValue = !decimalValue.equals(BigDecimal.ZERO);
}
else if (datatype.equals(XMLSchema.INTEGER)) {
BigInteger integerValue = literal.integerValue();
booleanValue = !integerValue.equals(BigInteger.ZERO);
}
else if (XMLDatatypeUtil.isIntegerDatatype(datatype)) {
booleanValue = literal.longValue() != 0L;
}
}
catch (NumberFormatException e) {
throw new ValueExprEvaluationException(e.getMessage(), e);
}

if (booleanValue != null) {
return valueFactory.createLiteral(booleanValue);
}
}
}
}

throw new ValueExprEvaluationException("Invalid argument for xsd:boolean cast: " + args[0]);
}
@Deprecated
public class BooleanCast extends org.eclipse.rdf4j.query.algebra.evaluation.function.xsd.BooleanCast {
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,117 +7,13 @@
*******************************************************************************/
package org.eclipse.rdf4j.query.algebra.evaluation.function;

import javax.xml.datatype.DatatypeConstants;
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.ValueFactory;
import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
import org.eclipse.rdf4j.model.vocabulary.XMLSchema;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;

/**
* A {@link Function} that tries to cast its argument to an <tt>xsd:dateTime</tt>.
*
* @author Arjohn Kampman
* @deprecated use {@link org.eclipse.rdf4j.query.algebra.evaluation.function.xsd.DateTimeCast} instead.
*/
public class DateTimeCast implements Function {

public String getURI() {
return XMLSchema.DATETIME.toString();
}

public Literal evaluate(ValueFactory valueFactory, Value... args)
throws ValueExprEvaluationException
{
if (args.length != 1) {
throw new ValueExprEvaluationException(
"xsd:dateTime cast requires exactly 1 argument, got " + args.length);
}

if (args[0] instanceof Literal) {
Literal literal = (Literal)args[0];
IRI datatype = literal.getDatatype();

if (QueryEvaluationUtil.isStringLiteral(literal)) {
String dateTimeValue = XMLDatatypeUtil.collapseWhiteSpace(literal.getLabel());
if (XMLDatatypeUtil.isValidDateTime(dateTimeValue)) {
return valueFactory.createLiteral(dateTimeValue, XMLSchema.DATETIME);
}
}
else if (datatype != null) {
if (datatype.equals(XMLSchema.DATETIME)) {
return literal;
}
if (datatype.equals(XMLSchema.DATE)) {
// If ST is xs:date, then let SYR be eg:convertYearToString(
// fn:year-from-date( SV )), let SMO be eg:convertTo2CharString(
// fn:month-from-date( SV )), let SDA be eg:convertTo2CharString(
// fn:day-from-date( SV )) and let STZ be eg:convertTZtoString(
// fn:timezone-from-date( SV )); TV is xs:dateTime( fn:concat(
// SYR , '-', SMO , '-', SDA , 'T00:00:00 ', STZ ) ).
try {
XMLGregorianCalendar calValue = literal.calendarValue();

int year = calValue.getYear();
int month = calValue.getMonth();
int day = calValue.getDay();
int timezoneOffset = calValue.getTimezone();

if (DatatypeConstants.FIELD_UNDEFINED != year
&& DatatypeConstants.FIELD_UNDEFINED != month
&& DatatypeConstants.FIELD_UNDEFINED != day)
{
StringBuilder dtBuilder = new StringBuilder();
dtBuilder.append(year);
dtBuilder.append("-");
if (month < 10) {
dtBuilder.append("0");
}
dtBuilder.append(month);
dtBuilder.append("-");
if (day < 10) {
dtBuilder.append("0");
}
dtBuilder.append(day);
dtBuilder.append("T00:00:00");
if (DatatypeConstants.FIELD_UNDEFINED != timezoneOffset) {
int minutes = Math.abs(timezoneOffset);
int hours = minutes / 60;
minutes = minutes - (hours * 60);
if (timezoneOffset > 0) {
dtBuilder.append("+");
}
else {
dtBuilder.append("-");
}
if (hours < 10) {
dtBuilder.append("0");
}
dtBuilder.append(hours);
dtBuilder.append(":");
if (minutes < 10) {
dtBuilder.append("0");
}
dtBuilder.append(minutes);
}

return valueFactory.createLiteral(dtBuilder.toString(), XMLSchema.DATETIME);
}
else {
throw new ValueExprEvaluationException("not a valid date value: " + literal);
}
}
catch (IllegalArgumentException e) {
throw new ValueExprEvaluationException("not a valid calendar value: " + literal);
}
}
}
}
@Deprecated
public class DateTimeCast extends org.eclipse.rdf4j.query.algebra.evaluation.function.xsd.DateTimeCast {

throw new ValueExprEvaluationException("Invalid argument for xsd:dateTime cast: " + args[0]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,73 +7,12 @@
*******************************************************************************/
package org.eclipse.rdf4j.query.algebra.evaluation.function;

import java.math.BigDecimal;

import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
import org.eclipse.rdf4j.model.vocabulary.XMLSchema;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;

/**
* A {@link Function} that tries to cast its argument to an <tt>xsd:decimal</tt>.
*
* @author Arjohn Kampman
* @deprecated use {@link org.eclipse.rdf4j.query.algebra.evaluation.function.xsd.DecimalCast} instead.
*/
public class DecimalCast implements Function {

public String getURI() {
return XMLSchema.DECIMAL.toString();
}

public Literal evaluate(ValueFactory valueFactory, Value... args)
throws ValueExprEvaluationException
{
if (args.length != 1) {
throw new ValueExprEvaluationException(
"xsd:decimal cast requires exactly 1 argument, got " + args.length);
}

if (args[0] instanceof Literal) {
Literal literal = (Literal)args[0];
IRI datatype = literal.getDatatype();

if (QueryEvaluationUtil.isStringLiteral(literal)) {
String decimalValue = XMLDatatypeUtil.collapseWhiteSpace(literal.getLabel());
if (XMLDatatypeUtil.isValidDecimal(decimalValue)) {
return valueFactory.createLiteral(decimalValue, XMLSchema.DECIMAL);
}
}
else if (datatype != null) {
if (datatype.equals(XMLSchema.DECIMAL)) {
return literal;
}
else if (XMLDatatypeUtil.isNumericDatatype(datatype)) {
// FIXME: floats and doubles must be processed separately, see
// http://www.w3.org/TR/xpath-functions/#casting-from-primitive-to-primitive
try {
BigDecimal decimalValue = literal.decimalValue();
return valueFactory.createLiteral(decimalValue.toPlainString(), XMLSchema.DECIMAL);
}
catch (NumberFormatException e) {
throw new ValueExprEvaluationException(e.getMessage(), e);
}
}
else if (datatype.equals(XMLSchema.BOOLEAN)) {
try {
return valueFactory.createLiteral(literal.booleanValue() ? "1.0" : "0.0",
XMLSchema.DECIMAL);
}
catch (IllegalArgumentException e) {
throw new ValueExprEvaluationException(e.getMessage(), e);
}
}
}
}

throw new ValueExprEvaluationException("Invalid argument for xsd:decimal cast: " + args[0]);
}
@Deprecated
public class DecimalCast extends org.eclipse.rdf4j.query.algebra.evaluation.function.xsd.DecimalCast {
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,70 +7,12 @@
*******************************************************************************/
package org.eclipse.rdf4j.query.algebra.evaluation.function;

import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
import org.eclipse.rdf4j.model.vocabulary.XMLSchema;
import org.eclipse.rdf4j.query.algebra.evaluation.ValueExprEvaluationException;
import org.eclipse.rdf4j.query.algebra.evaluation.util.QueryEvaluationUtil;

/**
* A {@link Function} that tries to cast its argument to an <tt>xsd:double</tt>.
*
* @author Arjohn Kampman
* @deprecated use {@link org.eclipse.rdf4j.query.algebra.evaluation.function.xsd.DoubleCast} instead.
*/
public class DoubleCast implements Function {

public String getURI() {
return XMLSchema.DOUBLE.toString();
}

public Literal evaluate(ValueFactory valueFactory, Value... args)
throws ValueExprEvaluationException
{
if (args.length != 1) {
throw new ValueExprEvaluationException(
"xsd:double cast requires exactly 1 argument, got " + args.length);
}

if (args[0] instanceof Literal) {
Literal literal = (Literal)args[0];
IRI datatype = literal.getDatatype();

if (QueryEvaluationUtil.isStringLiteral(literal)) {
String doubleValue = XMLDatatypeUtil.collapseWhiteSpace(literal.getLabel());
if (XMLDatatypeUtil.isValidDouble(doubleValue)) {
return valueFactory.createLiteral(doubleValue, XMLSchema.DOUBLE);
}
}
else if (datatype != null) {
if (datatype.equals(XMLSchema.DOUBLE)) {
return literal;
}
else if (XMLDatatypeUtil.isNumericDatatype(datatype)) {
// FIXME: doubles must be processed separately, see
// http://www.w3.org/TR/xpath-functions/#casting-from-primitive-to-primitive
try {
double doubleValue = literal.doubleValue();
return valueFactory.createLiteral(doubleValue);
}
catch (NumberFormatException e) {
throw new ValueExprEvaluationException(e.getMessage(), e);
}
}
else if (datatype.equals(XMLSchema.BOOLEAN)) {
try {
return valueFactory.createLiteral(literal.booleanValue() ? 1.0 : 0.0);
}
catch (IllegalArgumentException e) {
throw new ValueExprEvaluationException(e.getMessage(), e);
}
}
}
}

throw new ValueExprEvaluationException("Invalid argument for xsd:double cast: " + args[0]);
}
@Deprecated
public class DoubleCast extends org.eclipse.rdf4j.query.algebra.evaluation.function.xsd.DoubleCast {
}
Loading

0 comments on commit 4a15deb

Please sign in to comment.