/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package reportgen.math.reference.function;
import reportgen.prototype.context.Context;
import reportgen.math.complex.MathExpressionComplex;
import org.jdom.Element;
import reportgen.prototype.stream.SQLStream;
import reportgen.utils.ReportException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import reportgen.prototype.context.group.ContextGroup;
import reportgen.math.MathExpressionOperand;
import reportgen.math.reference.function.values.MathFunctionType;
/**
* математический элемент функция.
* Содержит два математических элемента.
* Все элементы в выражении должны быть операндами
* @author axe
*/
public class MathExpressionFunction extends MathExpressionComplex {
public static final ContextGroup GROUP = new FunctionContextGroup();
public static final String TAG = "function";
public static final String NAMEATTR = "name";
private MathFunctionType function;
public MathExpressionFunction(MathFunctionType function,
Context context) {
super(context);
this.function = function;
}
public MathExpressionFunction(Element element,
Context context) throws ReportException {
super(element, context);
String name = getStringAttribute(element, NAMEATTR);
function = context.getMathFunction(name);
}
@Override
protected void toXML(Element root) {
super.toXML(root);
root.setAttribute(NAMEATTR, function.getMnemonic());
}
@Override
public MathExpressionFunction makeClone() throws ReportException {
return new MathExpressionFunction(toXML(), getParentContext());
}
@Override
public ContextGroup getContextGroup() {
return GROUP;
}
@Override
protected String getRootTag() {
return TAG;
}
public MathFunctionType getType() {
return function;
}
public void setType(MathFunctionType type) {
function = type;
}
@Override
public String toString() {
String str = function.getTitle() + "(";
for(int i=0; i<children.size(); i++) {
str += children.get(i).toString();
if(i+1 < children.size()) {
str += ", ";
}
}
str += ")";
return str;
}
@Override
public void appendToQuery(SQLStream sql, Map model) throws ReportException {
sql.append(function.getTitle() + "(");
for(int i=0; i<children.size(); i++) {
children.get(i).appendToQuery(sql, model);
if(i+1 < children.size()) {
sql.append(", ");
}
}
sql.append(")");
}
@Override
public Class getCls() throws ReportException {
for(int i=0; i<children.size(); i++) {
if(!(children.get(i) instanceof MathExpressionOperand)) {
throw new ReportException("Все аргументы у функции должны быть операндами");
}
}
List<Class> operandClasses = new ArrayList<Class>();
for(int i=0; i<children.size(); i++) {
MathExpressionOperand operand = (MathExpressionOperand) children.get(i);
operandClasses.add(operand != null ? operand.getCls() : null);
}
return function.validate(operandClasses);
}
@Override
public Object getValue(Map constants) throws ReportException {
validate();
List<MathExpressionOperand> args = new ArrayList<MathExpressionOperand>();
for(int i=0; i<children.size(); i++) {
//dont check static cast, because of validation earlier
args.add((MathExpressionOperand)children.get(i));
}
return function.getValue(args, constants);
}
@Override
public Context getLocalContext() {
return function.getContext(super.getLocalContext());
}
}