All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openrdf.sesame.sail.query.MathExpr Maven / Gradle / Ivy

Go to download

Sesame is an open source Java framework for storing, querying and reasoning with RDF.

The newest version!
/*  Sesame - Storage and Querying architecture for RDF and RDF Schema
 *  Copyright (C) 2001-2006 Aduna
 *
 *  Contact:
 *  	Aduna
 *  	Prinses Julianaplein 14 b
 *  	3817 CS Amersfoort
 *  	The Netherlands
 *  	tel. +33 (0)33 465 99 87
 *  	fax. +33 (0)33 465 99 87
 *
 *  	http://aduna-software.com/
 *  	http://www.openrdf.org/
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.openrdf.sesame.sail.query;

import java.math.BigInteger;
import java.math.BigDecimal;
import java.util.Collection;

import org.openrdf.vocabulary.XmlSchema;
import org.openrdf.util.xml.XmlDatatypeUtil;

import org.openrdf.model.Literal;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.impl.LiteralImpl;
import org.openrdf.model.impl.URIImpl;

/**
 * A mathematical expression consisting an operator and two arguments.
 **/
public class MathExpr implements ValueExpr {

/*----------+
| Constants	|
+----------*/

	/** The plus (+) operator. **/
	public static final int PLUS = 0;

	/** The subtraction (-) operator. **/
	public static final int SUBTRACT = 1;

	/** The multiplication (*) operator. **/
	public static final int MULTIPLY = 2;

	/** The division (/) operator. **/
	public static final int DIVIDE = 3;

	/** The remainder (%) operator. **/
	public static final int REMAINDER = 4;


	/** http://www.w3.org/2001/XMLSchema#integer **/
	private static final URI XSD_INTEGER_URI = new URIImpl(XmlSchema.INTEGER);

	/** http://www.w3.org/2001/XMLSchema#double **/
	private static final URI XSD_DOUBLE_URI = new URIImpl(XmlSchema.DOUBLE);

/*----------+
| Variables |
+----------*/

	private ValueExpr _leftArg;
	private ValueExpr _rightArg;
	private int _operator;

/*-------------+
| Constructors |
+-------------*/

	public MathExpr(ValueExpr leftArg, ValueExpr rightArg, int op) {
		if (op < PLUS || op > REMAINDER) {
			throw new IllegalArgumentException("Illegal operator: " + op);
		}

		_leftArg = leftArg;
		_rightArg = rightArg;
		_operator = op;
	}

/*--------+
| Methods |
+--------*/

	public ValueExpr getLeftArg() {
		return _leftArg;
	}

	public ValueExpr getRightArg() {
		return _rightArg;
	}

	public int getOperator() {
		return _operator;
	}

	// implements StringExpr.getVariables(Collection)
	public void getVariables(Collection variables) {
		_leftArg.getVariables(variables);
		_rightArg.getVariables(variables);
	}

	// implements StringExpr.getString()
	public String getString() {
		Value value = getValue();

		if (value != null) {
			return ((Literal)value).getLabel();
		}

		return null;
	}

	// implements ValueExpr.getValue()
	public Value getValue() {
		// Do the math
		Value leftVal = _leftArg.getValue();
		Value rightVal = _rightArg.getValue();

		if (leftVal instanceof Literal && rightVal instanceof Literal) {
			return getValue((Literal)leftVal, (Literal)rightVal, _operator);
		}

		return null;
	}

	public static Literal getValue(Literal leftLit, Literal rightLit, int op) {
		String leftLabel = leftLit.getLabel();
		URI leftDatatype = leftLit.getDatatype();

		String rightLabel = rightLit.getLabel();
		URI rightDatatype = rightLit.getDatatype();

		if (leftDatatype == null || XmlDatatypeUtil.isIntegerDatatype(leftDatatype.getURI()) &&
			rightDatatype == null || XmlDatatypeUtil.isIntegerDatatype(rightDatatype.getURI()))
		{
			// Both arguments are, or could be, integers. Attempt an integer operation.
			try {
				BigInteger leftInt = new BigInteger(leftLabel);
				BigInteger rightInt = new BigInteger(rightLabel);

				BigInteger result = null;
				switch (op) {
					case PLUS     : result = leftInt.add(rightInt); break;
					case SUBTRACT : result = leftInt.subtract(rightInt); break;
					case MULTIPLY : result = leftInt.multiply(rightInt); break;
					case DIVIDE   : result = leftInt.divide(rightInt); break;
					case REMAINDER: result = leftInt.remainder(rightInt); break;

					default: throw new IllegalArgumentException("Unknown operator: " + op);
				}

				// Return the result as an xsd:integer
				return new LiteralImpl(result.toString(), XSD_INTEGER_URI);
			}
			catch (NumberFormatException e) {
				if (leftDatatype != null && rightDatatype != null) {
					// Both were specified to be integer, but apparently are not
					return null;
				}
				// else: type casting of untyped literal to an integer failed,
				// attempt decimal operation
			}
		}

		// Integer operation failed or does not apply, attempt floating point operation
		try {
			BigDecimal leftDec = new BigDecimal(leftLabel);
			BigDecimal rightDec = new BigDecimal(rightLabel);

			BigDecimal result = null;
			switch (op) {
				case PLUS     : result = leftDec.add(rightDec); break;
				case SUBTRACT : result = leftDec.subtract(rightDec); break;
				case MULTIPLY : result = leftDec.multiply(rightDec); break;
				case DIVIDE   : result = leftDec.divide(rightDec, 32, BigDecimal.ROUND_DOWN); break;
				case REMAINDER: return null; // Remainder is not applicable to floating point numbers

				default: throw new IllegalArgumentException("Unknown operator: " + op);
			}

			// Return the result as an xsd:double
			return new LiteralImpl(result.toString(), XSD_DOUBLE_URI);
		}
		catch (NumberFormatException e) {
			return null;
		}
	}

	public String toString() {
		StringBuffer buf = new StringBuffer(32);

		buf.append( _leftArg.toString() );

		switch (_operator) {
			case PLUS     : buf.append(" + "); break;
			case SUBTRACT    : buf.append(" - "); break;
			case MULTIPLY : buf.append(" * "); break;
			case DIVIDE   : buf.append(" / "); break;
			case REMAINDER: buf.append(" % "); break;
		}

		buf.append( _rightArg.toString() );

		return buf.toString();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy