| 1 16 package org.outerj.daisy.query.model.functions; 17 18 import org.outerj.daisy.query.QueryContext; 19 import org.outerj.daisy.query.model.AbstractFunction; 20 import org.outerj.daisy.query.model.ValueExpr; 21 import org.outerj.daisy.query.model.QValueType; 22 import org.outerj.daisy.query.model.SqlGenerationContext; 23 import org.outerj.daisy.repository.query.QueryException; 24 import org.outerj.daisy.repository.query.EvaluationContext; 25 import org.outerj.daisy.repository.Document; 26 import org.outerj.daisy.repository.Version; 27 28 import java.math.BigDecimal ; 29 import java.util.Locale ; 30 import java.util.Iterator ; 31 32 public abstract class AbstractBinaryMathFunction extends AbstractFunction { 33 public void prepare(QueryContext context) throws QueryException { 34 super.prepare(context); 35 if (params.size() != 2) 36 throw new QueryException("\"" + getFunctionName() + "\" requires exactly two parameters."); 37 38 Iterator paramsIt = params.iterator(); 39 while (paramsIt.hasNext()) { 40 ValueExpr valueExpr = (ValueExpr)paramsIt.next(); 41 if (!isNumeric(valueExpr)) 42 throw new QueryException("\"" + getFunctionName() + "\" can only be performed on numeric expressions, which this is not: " + valueExpr.getExpression()); 43 } 44 } 45 46 static boolean isNumeric(ValueExpr valueExpr) { 47 if (valueExpr.isSymbolicIdentifier()) 48 return false; 49 50 QValueType valueType = valueExpr.getValueType(); 51 return valueType == QValueType.UNDEFINED || valueType == QValueType.LONG || valueType == QValueType.DOUBLE || valueType == QValueType.DECIMAL; 52 } 53 54 public Object evaluate(QValueType valueType, EvaluationContext evaluationContext) throws QueryException { 55 BigDecimal value1 = toBigDecimal(getParam(0).evaluate(QValueType.DECIMAL, evaluationContext)); 56 BigDecimal value2 = toBigDecimal(getParam(1).evaluate(QValueType.DECIMAL, evaluationContext)); 57 return evaluate(value1, value2); 58 } 59 60 public Object evaluate(QValueType valueType, Document document, Version version, EvaluationContext evaluationContext) throws QueryException { 61 BigDecimal value1 = toBigDecimal(getParam(0).evaluate(QValueType.DECIMAL, document, version, evaluationContext)); 62 BigDecimal value2 = toBigDecimal(getParam(1).evaluate(QValueType.DECIMAL, document, version, evaluationContext)); 63 return evaluate(value1, value2); 64 } 65 66 private Object evaluate(BigDecimal value1, BigDecimal value2) { 67 if (value1 == null || value2 == null) 68 return null; 69 return performCalculation(value1, value2); 70 } 71 72 protected abstract Object performCalculation(BigDecimal value1, BigDecimal value2); 73 74 static BigDecimal toBigDecimal(Object value) { 75 if (value == null) 76 return null; 77 else if (value instanceof BigDecimal ) 78 return (BigDecimal )value; 79 else if (value instanceof Long ) 80 return new BigDecimal (((Long )value).longValue()); 81 else if (value instanceof Double ) 82 return new BigDecimal (((Double )value).doubleValue()); 83 else 84 throw new RuntimeException ("Unexpected type: " + value.getClass().getName()); 85 } 86 87 public String getExpression() { 88 StringBuffer expression = new StringBuffer (); 89 expression.append(" ("); 90 expression.append(getParam(0).getExpression()); 91 expression.append(getMathSymbol()); 92 expression.append(getParam(1).getExpression()); 93 expression.append(") "); 94 return expression.toString(); 95 } 96 97 public void generateSqlValueExpr(StringBuffer sql, SqlGenerationContext context) throws QueryException { 98 sql.append(" ("); 99 getParam(0).generateSqlValueExpr(sql, context); 100 sql.append(getMathSymbol()); 101 getParam(1).generateSqlValueExpr(sql, context); 102 sql.append(") "); 103 } 104 105 protected abstract String getMathSymbol(); 106 107 public QValueType getValueType() { 108 return QValueType.DECIMAL; 109 } 110 111 public String getTitle(Locale locale) { 112 return getExpression(); 113 } 114 115 public QValueType getOutputValueType() { 116 return QValueType.DECIMAL; 117 } 118 119 public Object getOutputValue(Document document, Version version, EvaluationContext evaluationContext) throws QueryException { 120 return evaluate(null, document, version, evaluationContext); 121 } 122 } 123 | Popular Tags |