/*
* Copyright 2009 DuraSpace.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mulgara.query.xpath;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.mulgara.query.functions.MulgaraFunction;
import org.mulgara.query.functions.MulgaraFunctionGroup;
/**
* Container for functions in the op pseudo-domain.
*
* @created Oct 5, 2009
* @author Paula Gearon
* @copyright © 2009 <a href="http://www.duraspace.org/">DuraSpace</a>
*/
public class OpFunctionGroup implements MulgaraFunctionGroup {
/** The prefix for the op: namespace */
static final String PREFIX = "op";
/** The op: namespace */
static final String NAMESPACE = PREFIX;
/**
* Get the prefix used for the namespace of these operations.
* @return The short string used for a prefix in a QName.
*/
public String getPrefix() {
return PREFIX;
}
/**
* Get the namespace of these operations.
* @return The string of the namespace URI.
*/
public String getNamespace() {
return NAMESPACE;
}
/**
* Get the set of SPARQL functions.
* @return A set of MulgaraFunction for this entire group.
*/
public Set<MulgaraFunction> getAllFunctions() {
Set<MulgaraFunction> functions = new HashSet<MulgaraFunction>();
functions.add(new NumericEqual());
functions.add(new NumericLessThan());
functions.add(new NumericGreaterThan());
functions.add(new NumericIntegerDivision());
functions.add(new NumericMod());
return functions;
}
/**
* Function to evaluate if two numbers are equal.
* @see http://www.w3.org/TR/xpath-functions/#func-numeric-equal
*/
static private class NumericEqual extends MulgaraFunction {
public String getName() { return "numeric-equal/2"; }
public int getArity() { return 2; }
public Object eval(List<?> args) {
Number left = (Number)args.get(0);
Number right = (Number)args.get(1);
return left.doubleValue() == right.doubleValue();
}
}
/**
* Function to evaluate if one number is less than another.
* @see http://www.w3.org/TR/xpath-functions/#func-numeric-less-than
*/
static private class NumericLessThan extends MulgaraFunction {
public String getName() { return "numeric-less-than/2"; }
public int getArity() { return 2; }
public Object eval(List<?> args) {
Number left = (Number)args.get(0);
Number right = (Number)args.get(1);
return left.doubleValue() < right.doubleValue();
}
}
/**
* Function to evaluate if one number is greater than another.
* @see http://www.w3.org/TR/xpath-functions/#func-numeric-greater-than
*/
static private class NumericGreaterThan extends MulgaraFunction {
public String getName() { return "numeric-greater-than/2"; }
public int getArity() { return 2; }
public Object eval(List<?> args) {
Number left = (Number)args.get(0);
Number right = (Number)args.get(1);
return left.doubleValue() > right.doubleValue();
}
}
/**
* Function to evaluate integer division between numbers. This does not meet the XPath semantics
* perfectly, but will work for many situations.
* @see http://www.w3.org/TR/xpath-functions/#func-numeric-integer-divide
*/
static private class NumericIntegerDivision extends MulgaraFunction {
public String getName() { return "numeric-integer-divide/2"; }
public int getArity() { return 2; }
public Object eval(List<?> args) {
Number left = (Number)args.get(0);
Number right = (Number)args.get(1);
if (left instanceof BigDecimal) {
return ((BigDecimal)left).divide(
(right instanceof BigDecimal) ? (BigDecimal)right : new BigDecimal(right.toString())
);
}
if (left instanceof BigInteger) {
return ((BigInteger)left).divide(
(right instanceof BigInteger) ? (BigInteger)right : new BigInteger(right.toString())
);
}
return Double.valueOf(left.doubleValue() / right.doubleValue()).longValue();
}
}
/**
* Function to evaluate the numeric mod operation. This does not meet the XPath semantics
* perfectly, but will work for most situations.
* @see http://www.w3.org/TR/xpath-functions/#func-numeric-mod
*/
static private class NumericMod extends MulgaraFunction {
public String getName() { return "numeric-mod/2"; }
public int getArity() { return 2; }
public Object eval(List<?> args) {
Number left = (Number)args.get(0);
Number right = (Number)args.get(1);
if (left instanceof Byte || left instanceof Short || left instanceof Integer || left instanceof Long) {
return left.longValue() % right.longValue();
}
if (left instanceof Float || left instanceof Double) {
return left.doubleValue() % right.doubleValue();
}
if (left instanceof BigDecimal) {
return ((BigDecimal)left).remainder(
(right instanceof BigDecimal) ? (BigDecimal)right : new BigDecimal(right.toString())
);
}
if (left instanceof BigInteger) {
return ((BigInteger)left).remainder(
(right instanceof BigInteger) ? (BigInteger)right : new BigInteger(right.toString())
);
}
return Double.valueOf(left.doubleValue() % right.doubleValue()).longValue();
}
}
}