blob: b3ba4ee43f81988c121093ac09b5c1268895d755 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.cocoon.forms.formmodel.algorithms;
import org.apache.avalon.framework.CascadingError;
import org.apache.cocoon.forms.datatype.Datatype;
import org.apache.cocoon.forms.formmodel.CannotYetResolveWarning;
import org.apache.cocoon.forms.formmodel.ExpressionContextImpl;
import org.apache.cocoon.forms.formmodel.Form;
import org.apache.cocoon.forms.formmodel.Widget;
import org.outerj.expression.Expression;
import org.outerj.expression.ExpressionContext;
import org.outerj.expression.ExpressionException;
/**
* An xreported expression based algorithm.
* <p>
* This algorithm can be used to write simple formulas, examples are :
* <ul>
* <li>20% VAT calculation : eval="(amount / 100) * 20"</li>
* <li>100$ volume discount : eval="If(amount > 1000,100,0)"
* (read: if amount is greater than 1000 then the result will be 100, otherwise 0)</li>
* <li>Number of boxes needed to carry that number of items : eval="Ceiling(items / boxsize)"</li>
* <li>Number of items you can add before another box is needed : eval="Reminder(items,boxside)"</li>
* </ul>
* </p>
* <p>
* Note: please take care that xreporter expressions are not that accurate when it comes to decimals. The default
* divide operator rounds the result, see http://issues.cocoondev.org/browse/XRP-115. Also consider that the
* available set of functions can be expanded implementing and using new ones. Please see
* <a href="http://outerthought.net/wqm/xreporter/en/expressions.html">
* http://outerthought.net/wqm/xreporter/en/expressions.html</a> for an overview of xreportes expressions and
* {@link org.apache.cocoon.forms.expression.IsNullFunction} or
* {@link org.apache.cocoon.forms.expression.StringFunction}
* for examples of custom xreporter functions.
* </p>
* @version $Id$
*/
public class SimpleFormula extends AbstractBaseAlgorithm {
protected Expression formula;
public boolean isSuitableFor(Datatype dataType) {
return dataType.getTypeClass().isAssignableFrom(formula.getResultType());
}
public Object calculate(Form form, Widget parent, Datatype datatype) {
ExpressionContext ctx = new ExpressionContextImpl(parent, true);
try {
return formula.evaluate(ctx);
} catch (CannotYetResolveWarning w) {
return null;
} catch (ExpressionException e) {
throw new CascadingError("Error evaluating calculated field formula", e);
}
}
/**
* @return Returns the formula.
*/
public Expression getFormula() {
return formula;
}
/**
* @param formula The formula to set.
*/
public void setFormula(Expression formula) {
this.formula = formula;
}
}